├── .gitattributes ├── .soliumrc.json ├── contracts ├── Coinflip.sol ├── Migrations.sol ├── SafeMath.sol └── provableAPI_0.5.sol ├── migrations ├── 1_initial_migration.js └── 2_deploy_contracts.js ├── package-lock.json ├── package.json ├── test └── .gitkeep └── truffle-config.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:recommended", 3 | "plugins": ["security"], 4 | "rules": { 5 | "no-call-value": "off" 6 | } 7 | } -------------------------------------------------------------------------------- /contracts/Coinflip.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import './provableAPI_0.5.sol'; 4 | import './SafeMath.sol'; 5 | 6 | contract Coinflip is usingProvable { 7 | using SafeMath for uint; 8 | 9 | struct Bet { 10 | address playerAddress; 11 | uint betValue; 12 | uint headsTails; 13 | uint setRandomPrice; 14 | } 15 | 16 | mapping(address => uint) public playerWinnings; 17 | mapping (address => Bet) public waiting; 18 | mapping (bytes32 => address) public afterWaiting; 19 | 20 | event logNewProvableQuery(string description); 21 | event sentQueryId(address caller, bytes32 indexed queryId); 22 | event callbackReceived(bytes32 indexed queryId, string description, uint256 amount); 23 | event userWithdrawal(address indexed caller, uint256 amount); 24 | 25 | uint public contractBalance; 26 | 27 | uint256 constant GAS_FOR_CALLBACK = 200000; 28 | uint256 constant NUM_RANDOM_BYTES_REQUESTED = 1; 29 | 30 | address payable public owner = msg.sender; 31 | 32 | bool public freeCallback = true; 33 | 34 | constructor() public payable{ 35 | owner = msg.sender; 36 | contractBalance = msg.value; 37 | } 38 | 39 | modifier onlyOwner() { 40 | require(msg.sender == owner); 41 | _; 42 | } 43 | 44 | /** 45 | *@notice This function simulates a coin flip which makes a call to the Provable oracle for 46 | * a random number. 47 | *@dev The function first checks if this is the very first call to the Provable oracle in order 48 | * for the user to not pay for the first free call. This also adds user values to two different 49 | * mappings: 'waiting' and 'afterWaiting.' Both mappings are necessary in order to bridge the 50 | * user's address (which we has access to here with msg.sender) and the user's queryId sent from 51 | * Provable after the function call. 52 | * 53 | *@param oneZero - The numerical value of heads(0) or tails(1) 54 | */ 55 | 56 | function flip(uint256 oneZero) public payable { 57 | require(contractBalance > msg.value, "We don't have enough funds"); 58 | uint256 randomPrice; 59 | 60 | if(freeCallback == false){ 61 | randomPrice = getQueryPrice(); 62 | } else { 63 | freeCallback = false; 64 | randomPrice = 0; 65 | } 66 | 67 | uint256 QUERY_EXECUTION_DELAY = 0; 68 | bytes32 queryId = provable_newRandomDSQuery( 69 | QUERY_EXECUTION_DELAY, 70 | NUM_RANDOM_BYTES_REQUESTED, 71 | GAS_FOR_CALLBACK 72 | ); 73 | emit logNewProvableQuery("Message sent. Waiting for an answer..."); 74 | emit sentQueryId(msg.sender, queryId); 75 | 76 | afterWaiting[queryId] = msg.sender; 77 | 78 | Bet memory newBetter; 79 | newBetter.playerAddress = msg.sender; 80 | newBetter.betValue = msg.value; 81 | newBetter.headsTails = oneZero; 82 | newBetter.setRandomPrice = randomPrice; 83 | 84 | waiting[msg.sender] = newBetter; 85 | } 86 | 87 | function __callback(bytes32 _queryId, string memory _result) public { 88 | require(msg.sender == provable_cbAddress()); 89 | 90 | //turn number into 1 or 0 91 | uint256 flipResult = SafeMath.mod(uint256(keccak256(abi.encodePacked(_result))), 2); 92 | 93 | //linking new mapping with new struct 94 | address _player = afterWaiting[_queryId]; 95 | 96 | Bet memory postBet = waiting[_player]; 97 | 98 | 99 | if(flipResult == postBet.headsTails){ 100 | //winner 101 | uint winAmount = SafeMath.sub(SafeMath.mul(postBet.betValue, 2), postBet.setRandomPrice); 102 | contractBalance = SafeMath.sub(contractBalance, postBet.betValue); 103 | playerWinnings[_player] = SafeMath.add(playerWinnings[_player], winAmount); 104 | 105 | /** 106 | * @notice The following commented commands mirror the above commands sans SafeMath for readability. 107 | * 108 | * uint winAmount = (postBet.betValue * 2) - postBet.setRandomPrice; 109 | * contractBalance -= postBet.betValue; 110 | * playerWinnings[_player] += winAmount; 111 | */ 112 | 113 | emit callbackReceived(_queryId, "Winner", postBet.betValue); 114 | } else { 115 | //loser 116 | contractBalance = SafeMath.add(contractBalance, SafeMath.sub(postBet.betValue, postBet.setRandomPrice)); 117 | /** 118 | * @notice For readability--see previous comment. 119 | * 120 | * contractBalance += (postBet.betValue - postBet.setRandomPrice); 121 | */ 122 | emit callbackReceived(_queryId, "Loser", postBet.betValue); 123 | } 124 | } 125 | 126 | //combine gas and randomTx fee 127 | function getQueryPrice() internal returns(uint256 _price) { 128 | _price = provable_getPrice("price", GAS_FOR_CALLBACK); 129 | } 130 | 131 | 132 | function withdrawUserWinnings() public { 133 | require(playerWinnings[msg.sender] > 0, "No funds to withdraw"); 134 | uint toTransfer = playerWinnings[msg.sender]; 135 | playerWinnings[msg.sender] = 0; 136 | msg.sender.transfer(toTransfer); 137 | emit userWithdrawal(msg.sender, toTransfer); 138 | } 139 | 140 | function getWinningsBalance() public view returns(uint){ 141 | return playerWinnings[msg.sender]; 142 | } 143 | 144 | /** 145 | *@notice The following functions are reserved for the owner of the contract. 146 | */ 147 | 148 | function fundContract() public payable onlyOwner { 149 | contractBalance = SafeMath.add(contractBalance, msg.value); 150 | } 151 | 152 | function fundWinnings() public payable onlyOwner { 153 | playerWinnings[msg.sender] = SafeMath.add(playerWinnings[msg.sender], msg.value); 154 | } 155 | 156 | function withdrawAll() public onlyOwner { 157 | uint toTransfer = contractBalance; 158 | contractBalance = 0; 159 | msg.sender.transfer(toTransfer); 160 | } 161 | 162 | } -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner = msg.sender; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | require( 10 | msg.sender == owner, 11 | "This function is restricted to the contract's owner" 12 | ); 13 | _; 14 | } 15 | 16 | function setCompleted(uint completed) public restricted { 17 | last_completed_migration = completed; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | /** 4 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 5 | * checks. 6 | * 7 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 8 | * in bugs, because programmers usually assume that an overflow raises an 9 | * error, which is the standard behavior in high level programming languages. 10 | * `SafeMath` restores this intuition by reverting the transaction when an 11 | * operation overflows. 12 | * 13 | * Using this library instead of the unchecked operations eliminates an entire 14 | * class of bugs, so it's recommended to use it always. 15 | */ 16 | library SafeMath { 17 | /** 18 | * @dev Returns the addition of two unsigned integers, reverting on 19 | * overflow. 20 | * 21 | * Counterpart to Solidity's `+` operator. 22 | * 23 | * Requirements: 24 | * - Addition cannot overflow. 25 | */ 26 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 27 | uint256 c = a + b; 28 | require(c >= a, "SafeMath: addition overflow"); 29 | 30 | return c; 31 | } 32 | 33 | /** 34 | * @dev Returns the subtraction of two unsigned integers, reverting on 35 | * overflow (when the result is negative). 36 | * 37 | * Counterpart to Solidity's `-` operator. 38 | * 39 | * Requirements: 40 | * - Subtraction cannot overflow. 41 | */ 42 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 43 | require(b <= a, "SafeMath: subtraction overflow"); 44 | uint256 c = a - b; 45 | 46 | return c; 47 | } 48 | 49 | /** 50 | * @dev Returns the multiplication of two unsigned integers, reverting on 51 | * overflow. 52 | * 53 | * Counterpart to Solidity's `*` operator. 54 | * 55 | * Requirements: 56 | * - Multiplication cannot overflow. 57 | */ 58 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 59 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 60 | // benefit is lost if 'b' is also tested. 61 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 62 | if (a == 0) { 63 | return 0; 64 | } 65 | 66 | uint256 c = a * b; 67 | require(c / a == b, "SafeMath: multiplication overflow"); 68 | 69 | return c; 70 | } 71 | 72 | /** 73 | * @dev Returns the integer division of two unsigned integers. Reverts on 74 | * division by zero. The result is rounded towards zero. 75 | * 76 | * Counterpart to Solidity's `/` operator. Note: this function uses a 77 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 78 | * uses an invalid opcode to revert (consuming all remaining gas). 79 | * 80 | * Requirements: 81 | * - The divisor cannot be zero. 82 | */ 83 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 84 | // Solidity only automatically asserts when dividing by 0 85 | require(b > 0, "SafeMath: division by zero"); 86 | uint256 c = a / b; 87 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 88 | 89 | return c; 90 | } 91 | 92 | /** 93 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 94 | * Reverts when dividing by zero. 95 | * 96 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 97 | * opcode (which leaves remaining gas untouched) while Solidity uses an 98 | * invalid opcode to revert (consuming all remaining gas). 99 | * 100 | * Requirements: 101 | * - The divisor cannot be zero. 102 | */ 103 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 104 | require(b != 0, "SafeMath: modulo by zero"); 105 | return a % b; 106 | } 107 | } -------------------------------------------------------------------------------- /contracts/provableAPI_0.5.sol: -------------------------------------------------------------------------------- 1 | // 2 | /* 3 | Copyright (c) 2015-2016 Oraclize SRL 4 | Copyright (c) 2016-2019 Oraclize LTD 5 | Copyright (c) 2019 Provable Things Limited 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | pragma solidity >= 0.5.0 < 0.6.0; // Incompatible compiler version - please select a compiler within the stated pragma range, or use a different version of the provableAPI! 23 | 24 | // Dummy contract only used to emit to end-user they are using wrong solc 25 | contract solcChecker { 26 | /* INCOMPATIBLE SOLC: import the following instead: "github.com/oraclize/ethereum-api/oraclizeAPI_0.4.sol" */ function f(bytes calldata x) external; 27 | } 28 | 29 | contract ProvableI { 30 | 31 | address public cbAddress; 32 | 33 | function setProofType(byte _proofType) external; 34 | function setCustomGasPrice(uint _gasPrice) external; 35 | function getPrice(string memory _datasource) public returns (uint _dsprice); 36 | function randomDS_getSessionPubKeyHash() external view returns (bytes32 _sessionKeyHash); 37 | function getPrice(string memory _datasource, uint _gasLimit) public returns (uint _dsprice); 38 | function queryN(uint _timestamp, string memory _datasource, bytes memory _argN) public payable returns (bytes32 _id); 39 | function query(uint _timestamp, string calldata _datasource, string calldata _arg) external payable returns (bytes32 _id); 40 | function query2(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2) public payable returns (bytes32 _id); 41 | function query_withGasLimit(uint _timestamp, string calldata _datasource, string calldata _arg, uint _gasLimit) external payable returns (bytes32 _id); 42 | function queryN_withGasLimit(uint _timestamp, string calldata _datasource, bytes calldata _argN, uint _gasLimit) external payable returns (bytes32 _id); 43 | function query2_withGasLimit(uint _timestamp, string calldata _datasource, string calldata _arg1, string calldata _arg2, uint _gasLimit) external payable returns (bytes32 _id); 44 | } 45 | 46 | contract OracleAddrResolverI { 47 | function getAddress() public returns (address _address); 48 | } 49 | /* 50 | Begin solidity-cborutils 51 | https://github.com/smartcontractkit/solidity-cborutils 52 | MIT License 53 | Copyright (c) 2018 SmartContract ChainLink, Ltd. 54 | Permission is hereby granted, free of charge, to any person obtaining a copy 55 | of this software and associated documentation files (the "Software"), to deal 56 | in the Software without restriction, including without limitation the rights 57 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 58 | copies of the Software, and to permit persons to whom the Software is 59 | furnished to do so, subject to the following conditions: 60 | The above copyright notice and this permission notice shall be included in all 61 | copies or substantial portions of the Software. 62 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 66 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 67 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 68 | SOFTWARE. 69 | */ 70 | library Buffer { 71 | 72 | struct buffer { 73 | bytes buf; 74 | uint capacity; 75 | } 76 | 77 | function init(buffer memory _buf, uint _capacity) internal pure { 78 | uint capacity = _capacity; 79 | if (capacity % 32 != 0) { 80 | capacity += 32 - (capacity % 32); 81 | } 82 | _buf.capacity = capacity; // Allocate space for the buffer data 83 | assembly { 84 | let ptr := mload(0x40) 85 | mstore(_buf, ptr) 86 | mstore(ptr, 0) 87 | mstore(0x40, add(ptr, capacity)) 88 | } 89 | } 90 | 91 | function resize(buffer memory _buf, uint _capacity) private pure { 92 | bytes memory oldbuf = _buf.buf; 93 | init(_buf, _capacity); 94 | append(_buf, oldbuf); 95 | } 96 | 97 | function max(uint _a, uint _b) private pure returns (uint _max) { 98 | if (_a > _b) { 99 | return _a; 100 | } 101 | return _b; 102 | } 103 | /** 104 | * @dev Appends a byte array to the end of the buffer. Resizes if doing so 105 | * would exceed the capacity of the buffer. 106 | * @param _buf The buffer to append to. 107 | * @param _data The data to append. 108 | * @return The original buffer. 109 | * 110 | */ 111 | function append(buffer memory _buf, bytes memory _data) internal pure returns (buffer memory _buffer) { 112 | if (_data.length + _buf.buf.length > _buf.capacity) { 113 | resize(_buf, max(_buf.capacity, _data.length) * 2); 114 | } 115 | uint dest; 116 | uint src; 117 | uint len = _data.length; 118 | assembly { 119 | let bufptr := mload(_buf) // Memory address of the buffer data 120 | let buflen := mload(bufptr) // Length of existing buffer data 121 | dest := add(add(bufptr, buflen), 32) // Start address = buffer address + buffer length + sizeof(buffer length) 122 | mstore(bufptr, add(buflen, mload(_data))) // Update buffer length 123 | src := add(_data, 32) 124 | } 125 | for(; len >= 32; len -= 32) { // Copy word-length chunks while possible 126 | assembly { 127 | mstore(dest, mload(src)) 128 | } 129 | dest += 32; 130 | src += 32; 131 | } 132 | uint mask = 256 ** (32 - len) - 1; // Copy remaining bytes 133 | assembly { 134 | let srcpart := and(mload(src), not(mask)) 135 | let destpart := and(mload(dest), mask) 136 | mstore(dest, or(destpart, srcpart)) 137 | } 138 | return _buf; 139 | } 140 | /** 141 | * 142 | * @dev Appends a byte to the end of the buffer. Resizes if doing so would 143 | * exceed the capacity of the buffer. 144 | * @param _buf The buffer to append to. 145 | * @param _data The data to append. 146 | * @return The original buffer. 147 | * 148 | */ 149 | function append(buffer memory _buf, uint8 _data) internal pure { 150 | if (_buf.buf.length + 1 > _buf.capacity) { 151 | resize(_buf, _buf.capacity * 2); 152 | } 153 | assembly { 154 | let bufptr := mload(_buf) // Memory address of the buffer data 155 | let buflen := mload(bufptr) // Length of existing buffer data 156 | let dest := add(add(bufptr, buflen), 32) // Address = buffer address + buffer length + sizeof(buffer length) 157 | mstore8(dest, _data) 158 | mstore(bufptr, add(buflen, 1)) // Update buffer length 159 | } 160 | } 161 | /** 162 | * 163 | * @dev Appends a byte to the end of the buffer. Resizes if doing so would 164 | * exceed the capacity of the buffer. 165 | * @param _buf The buffer to append to. 166 | * @param _data The data to append. 167 | * @return The original buffer. 168 | * 169 | */ 170 | function appendInt(buffer memory _buf, uint _data, uint _len) internal pure returns (buffer memory _buffer) { 171 | if (_len + _buf.buf.length > _buf.capacity) { 172 | resize(_buf, max(_buf.capacity, _len) * 2); 173 | } 174 | uint mask = 256 ** _len - 1; 175 | assembly { 176 | let bufptr := mload(_buf) // Memory address of the buffer data 177 | let buflen := mload(bufptr) // Length of existing buffer data 178 | let dest := add(add(bufptr, buflen), _len) // Address = buffer address + buffer length + sizeof(buffer length) + len 179 | mstore(dest, or(and(mload(dest), not(mask)), _data)) 180 | mstore(bufptr, add(buflen, _len)) // Update buffer length 181 | } 182 | return _buf; 183 | } 184 | } 185 | 186 | library CBOR { 187 | 188 | using Buffer for Buffer.buffer; 189 | 190 | uint8 private constant MAJOR_TYPE_INT = 0; 191 | uint8 private constant MAJOR_TYPE_MAP = 5; 192 | uint8 private constant MAJOR_TYPE_BYTES = 2; 193 | uint8 private constant MAJOR_TYPE_ARRAY = 4; 194 | uint8 private constant MAJOR_TYPE_STRING = 3; 195 | uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; 196 | uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; 197 | 198 | function encodeType(Buffer.buffer memory _buf, uint8 _major, uint _value) private pure { 199 | if (_value <= 23) { 200 | _buf.append(uint8((_major << 5) | _value)); 201 | } else if (_value <= 0xFF) { 202 | _buf.append(uint8((_major << 5) | 24)); 203 | _buf.appendInt(_value, 1); 204 | } else if (_value <= 0xFFFF) { 205 | _buf.append(uint8((_major << 5) | 25)); 206 | _buf.appendInt(_value, 2); 207 | } else if (_value <= 0xFFFFFFFF) { 208 | _buf.append(uint8((_major << 5) | 26)); 209 | _buf.appendInt(_value, 4); 210 | } else if (_value <= 0xFFFFFFFFFFFFFFFF) { 211 | _buf.append(uint8((_major << 5) | 27)); 212 | _buf.appendInt(_value, 8); 213 | } 214 | } 215 | 216 | function encodeIndefiniteLengthType(Buffer.buffer memory _buf, uint8 _major) private pure { 217 | _buf.append(uint8((_major << 5) | 31)); 218 | } 219 | 220 | function encodeUInt(Buffer.buffer memory _buf, uint _value) internal pure { 221 | encodeType(_buf, MAJOR_TYPE_INT, _value); 222 | } 223 | 224 | function encodeInt(Buffer.buffer memory _buf, int _value) internal pure { 225 | if (_value >= 0) { 226 | encodeType(_buf, MAJOR_TYPE_INT, uint(_value)); 227 | } else { 228 | encodeType(_buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - _value)); 229 | } 230 | } 231 | 232 | function encodeBytes(Buffer.buffer memory _buf, bytes memory _value) internal pure { 233 | encodeType(_buf, MAJOR_TYPE_BYTES, _value.length); 234 | _buf.append(_value); 235 | } 236 | 237 | function encodeString(Buffer.buffer memory _buf, string memory _value) internal pure { 238 | encodeType(_buf, MAJOR_TYPE_STRING, bytes(_value).length); 239 | _buf.append(bytes(_value)); 240 | } 241 | 242 | function startArray(Buffer.buffer memory _buf) internal pure { 243 | encodeIndefiniteLengthType(_buf, MAJOR_TYPE_ARRAY); 244 | } 245 | 246 | function startMap(Buffer.buffer memory _buf) internal pure { 247 | encodeIndefiniteLengthType(_buf, MAJOR_TYPE_MAP); 248 | } 249 | 250 | function endSequence(Buffer.buffer memory _buf) internal pure { 251 | encodeIndefiniteLengthType(_buf, MAJOR_TYPE_CONTENT_FREE); 252 | } 253 | } 254 | /* 255 | End solidity-cborutils 256 | */ 257 | contract usingProvable { 258 | 259 | using CBOR for Buffer.buffer; 260 | 261 | ProvableI provable; 262 | OracleAddrResolverI OAR; 263 | 264 | uint constant day = 60 * 60 * 24; 265 | uint constant week = 60 * 60 * 24 * 7; 266 | uint constant month = 60 * 60 * 24 * 30; 267 | 268 | byte constant proofType_NONE = 0x00; 269 | byte constant proofType_Ledger = 0x30; 270 | byte constant proofType_Native = 0xF0; 271 | byte constant proofStorage_IPFS = 0x01; 272 | byte constant proofType_Android = 0x40; 273 | byte constant proofType_TLSNotary = 0x10; 274 | 275 | string provable_network_name; 276 | uint8 constant networkID_auto = 0; 277 | uint8 constant networkID_morden = 2; 278 | uint8 constant networkID_mainnet = 1; 279 | uint8 constant networkID_testnet = 2; 280 | uint8 constant networkID_consensys = 161; 281 | 282 | mapping(bytes32 => bytes32) provable_randomDS_args; 283 | mapping(bytes32 => bool) provable_randomDS_sessionKeysHashVerified; 284 | 285 | modifier provableAPI { 286 | if ((address(OAR) == address(0)) || (getCodeSize(address(OAR)) == 0)) { 287 | provable_setNetwork(networkID_auto); 288 | } 289 | if (address(provable) != OAR.getAddress()) { 290 | provable = ProvableI(OAR.getAddress()); 291 | } 292 | _; 293 | } 294 | 295 | modifier provable_randomDS_proofVerify(bytes32 _queryId, string memory _result, bytes memory _proof) { 296 | // RandomDS Proof Step 1: The prefix has to match 'LP\x01' (Ledger Proof version 1) 297 | require((_proof[0] == "L") && (_proof[1] == "P") && (uint8(_proof[2]) == uint8(1))); 298 | bool proofVerified = provable_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), provable_getNetworkName()); 299 | require(proofVerified); 300 | _; 301 | } 302 | 303 | function provable_setNetwork(uint8 _networkID) internal returns (bool _networkSet) { 304 | _networkID; // NOTE: Silence the warning and remain backwards compatible 305 | return provable_setNetwork(); 306 | } 307 | 308 | function provable_setNetworkName(string memory _network_name) internal { 309 | provable_network_name = _network_name; 310 | } 311 | 312 | function provable_getNetworkName() internal view returns (string memory _networkName) { 313 | return provable_network_name; 314 | } 315 | 316 | function provable_setNetwork() internal returns (bool _networkSet) { 317 | if (getCodeSize(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed) > 0) { //mainnet 318 | OAR = OracleAddrResolverI(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed); 319 | provable_setNetworkName("eth_mainnet"); 320 | return true; 321 | } 322 | if (getCodeSize(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1) > 0) { //ropsten testnet 323 | OAR = OracleAddrResolverI(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1); 324 | provable_setNetworkName("eth_ropsten3"); 325 | return true; 326 | } 327 | if (getCodeSize(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e) > 0) { //kovan testnet 328 | OAR = OracleAddrResolverI(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e); 329 | provable_setNetworkName("eth_kovan"); 330 | return true; 331 | } 332 | if (getCodeSize(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48) > 0) { //rinkeby testnet 333 | OAR = OracleAddrResolverI(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48); 334 | provable_setNetworkName("eth_rinkeby"); 335 | return true; 336 | } 337 | if (getCodeSize(0xa2998EFD205FB9D4B4963aFb70778D6354ad3A41) > 0) { //goerli testnet 338 | OAR = OracleAddrResolverI(0xa2998EFD205FB9D4B4963aFb70778D6354ad3A41); 339 | provable_setNetworkName("eth_goerli"); 340 | return true; 341 | } 342 | if (getCodeSize(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475) > 0) { //ethereum-bridge 343 | OAR = OracleAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475); 344 | return true; 345 | } 346 | if (getCodeSize(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF) > 0) { //ether.camp ide 347 | OAR = OracleAddrResolverI(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF); 348 | return true; 349 | } 350 | if (getCodeSize(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA) > 0) { //browser-solidity 351 | OAR = OracleAddrResolverI(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA); 352 | return true; 353 | } 354 | return false; 355 | } 356 | /** 357 | * @dev The following `__callback` functions are just placeholders ideally 358 | * meant to be defined in child contract when proofs are used. 359 | * The function bodies simply silence compiler warnings. 360 | */ 361 | function __callback(bytes32 _myid, string memory _result) public { 362 | __callback(_myid, _result, new bytes(0)); 363 | } 364 | 365 | function __callback(bytes32 _myid, string memory _result, bytes memory _proof) public { 366 | _myid; _result; _proof; 367 | provable_randomDS_args[bytes32(0)] = bytes32(0); 368 | } 369 | 370 | function provable_getPrice(string memory _datasource) provableAPI internal returns (uint _queryPrice) { 371 | return provable.getPrice(_datasource); 372 | } 373 | 374 | function provable_getPrice(string memory _datasource, uint _gasLimit) provableAPI internal returns (uint _queryPrice) { 375 | return provable.getPrice(_datasource, _gasLimit); 376 | } 377 | 378 | function provable_query(string memory _datasource, string memory _arg) provableAPI internal returns (bytes32 _id) { 379 | uint price = provable.getPrice(_datasource); 380 | if (price > 1 ether + tx.gasprice * 200000) { 381 | return 0; // Unexpectedly high price 382 | } 383 | return provable.query.value(price)(0, _datasource, _arg); 384 | } 385 | 386 | function provable_query(uint _timestamp, string memory _datasource, string memory _arg) provableAPI internal returns (bytes32 _id) { 387 | uint price = provable.getPrice(_datasource); 388 | if (price > 1 ether + tx.gasprice * 200000) { 389 | return 0; // Unexpectedly high price 390 | } 391 | return provable.query.value(price)(_timestamp, _datasource, _arg); 392 | } 393 | 394 | function provable_query(uint _timestamp, string memory _datasource, string memory _arg, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 395 | uint price = provable.getPrice(_datasource,_gasLimit); 396 | if (price > 1 ether + tx.gasprice * _gasLimit) { 397 | return 0; // Unexpectedly high price 398 | } 399 | return provable.query_withGasLimit.value(price)(_timestamp, _datasource, _arg, _gasLimit); 400 | } 401 | 402 | function provable_query(string memory _datasource, string memory _arg, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 403 | uint price = provable.getPrice(_datasource, _gasLimit); 404 | if (price > 1 ether + tx.gasprice * _gasLimit) { 405 | return 0; // Unexpectedly high price 406 | } 407 | return provable.query_withGasLimit.value(price)(0, _datasource, _arg, _gasLimit); 408 | } 409 | 410 | function provable_query(string memory _datasource, string memory _arg1, string memory _arg2) provableAPI internal returns (bytes32 _id) { 411 | uint price = provable.getPrice(_datasource); 412 | if (price > 1 ether + tx.gasprice * 200000) { 413 | return 0; // Unexpectedly high price 414 | } 415 | return provable.query2.value(price)(0, _datasource, _arg1, _arg2); 416 | } 417 | 418 | function provable_query(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2) provableAPI internal returns (bytes32 _id) { 419 | uint price = provable.getPrice(_datasource); 420 | if (price > 1 ether + tx.gasprice * 200000) { 421 | return 0; // Unexpectedly high price 422 | } 423 | return provable.query2.value(price)(_timestamp, _datasource, _arg1, _arg2); 424 | } 425 | 426 | function provable_query(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 427 | uint price = provable.getPrice(_datasource, _gasLimit); 428 | if (price > 1 ether + tx.gasprice * _gasLimit) { 429 | return 0; // Unexpectedly high price 430 | } 431 | return provable.query2_withGasLimit.value(price)(_timestamp, _datasource, _arg1, _arg2, _gasLimit); 432 | } 433 | 434 | function provable_query(string memory _datasource, string memory _arg1, string memory _arg2, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 435 | uint price = provable.getPrice(_datasource, _gasLimit); 436 | if (price > 1 ether + tx.gasprice * _gasLimit) { 437 | return 0; // Unexpectedly high price 438 | } 439 | return provable.query2_withGasLimit.value(price)(0, _datasource, _arg1, _arg2, _gasLimit); 440 | } 441 | 442 | function provable_query(string memory _datasource, string[] memory _argN) provableAPI internal returns (bytes32 _id) { 443 | uint price = provable.getPrice(_datasource); 444 | if (price > 1 ether + tx.gasprice * 200000) { 445 | return 0; // Unexpectedly high price 446 | } 447 | bytes memory args = stra2cbor(_argN); 448 | return provable.queryN.value(price)(0, _datasource, args); 449 | } 450 | 451 | function provable_query(uint _timestamp, string memory _datasource, string[] memory _argN) provableAPI internal returns (bytes32 _id) { 452 | uint price = provable.getPrice(_datasource); 453 | if (price > 1 ether + tx.gasprice * 200000) { 454 | return 0; // Unexpectedly high price 455 | } 456 | bytes memory args = stra2cbor(_argN); 457 | return provable.queryN.value(price)(_timestamp, _datasource, args); 458 | } 459 | 460 | function provable_query(uint _timestamp, string memory _datasource, string[] memory _argN, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 461 | uint price = provable.getPrice(_datasource, _gasLimit); 462 | if (price > 1 ether + tx.gasprice * _gasLimit) { 463 | return 0; // Unexpectedly high price 464 | } 465 | bytes memory args = stra2cbor(_argN); 466 | return provable.queryN_withGasLimit.value(price)(_timestamp, _datasource, args, _gasLimit); 467 | } 468 | 469 | function provable_query(string memory _datasource, string[] memory _argN, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 470 | uint price = provable.getPrice(_datasource, _gasLimit); 471 | if (price > 1 ether + tx.gasprice * _gasLimit) { 472 | return 0; // Unexpectedly high price 473 | } 474 | bytes memory args = stra2cbor(_argN); 475 | return provable.queryN_withGasLimit.value(price)(0, _datasource, args, _gasLimit); 476 | } 477 | 478 | function provable_query(string memory _datasource, string[1] memory _args) provableAPI internal returns (bytes32 _id) { 479 | string[] memory dynargs = new string[](1); 480 | dynargs[0] = _args[0]; 481 | return provable_query(_datasource, dynargs); 482 | } 483 | 484 | function provable_query(uint _timestamp, string memory _datasource, string[1] memory _args) provableAPI internal returns (bytes32 _id) { 485 | string[] memory dynargs = new string[](1); 486 | dynargs[0] = _args[0]; 487 | return provable_query(_timestamp, _datasource, dynargs); 488 | } 489 | 490 | function provable_query(uint _timestamp, string memory _datasource, string[1] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 491 | string[] memory dynargs = new string[](1); 492 | dynargs[0] = _args[0]; 493 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 494 | } 495 | 496 | function provable_query(string memory _datasource, string[1] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 497 | string[] memory dynargs = new string[](1); 498 | dynargs[0] = _args[0]; 499 | return provable_query(_datasource, dynargs, _gasLimit); 500 | } 501 | 502 | function provable_query(string memory _datasource, string[2] memory _args) provableAPI internal returns (bytes32 _id) { 503 | string[] memory dynargs = new string[](2); 504 | dynargs[0] = _args[0]; 505 | dynargs[1] = _args[1]; 506 | return provable_query(_datasource, dynargs); 507 | } 508 | 509 | function provable_query(uint _timestamp, string memory _datasource, string[2] memory _args) provableAPI internal returns (bytes32 _id) { 510 | string[] memory dynargs = new string[](2); 511 | dynargs[0] = _args[0]; 512 | dynargs[1] = _args[1]; 513 | return provable_query(_timestamp, _datasource, dynargs); 514 | } 515 | 516 | function provable_query(uint _timestamp, string memory _datasource, string[2] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 517 | string[] memory dynargs = new string[](2); 518 | dynargs[0] = _args[0]; 519 | dynargs[1] = _args[1]; 520 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 521 | } 522 | 523 | function provable_query(string memory _datasource, string[2] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 524 | string[] memory dynargs = new string[](2); 525 | dynargs[0] = _args[0]; 526 | dynargs[1] = _args[1]; 527 | return provable_query(_datasource, dynargs, _gasLimit); 528 | } 529 | 530 | function provable_query(string memory _datasource, string[3] memory _args) provableAPI internal returns (bytes32 _id) { 531 | string[] memory dynargs = new string[](3); 532 | dynargs[0] = _args[0]; 533 | dynargs[1] = _args[1]; 534 | dynargs[2] = _args[2]; 535 | return provable_query(_datasource, dynargs); 536 | } 537 | 538 | function provable_query(uint _timestamp, string memory _datasource, string[3] memory _args) provableAPI internal returns (bytes32 _id) { 539 | string[] memory dynargs = new string[](3); 540 | dynargs[0] = _args[0]; 541 | dynargs[1] = _args[1]; 542 | dynargs[2] = _args[2]; 543 | return provable_query(_timestamp, _datasource, dynargs); 544 | } 545 | 546 | function provable_query(uint _timestamp, string memory _datasource, string[3] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 547 | string[] memory dynargs = new string[](3); 548 | dynargs[0] = _args[0]; 549 | dynargs[1] = _args[1]; 550 | dynargs[2] = _args[2]; 551 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 552 | } 553 | 554 | function provable_query(string memory _datasource, string[3] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 555 | string[] memory dynargs = new string[](3); 556 | dynargs[0] = _args[0]; 557 | dynargs[1] = _args[1]; 558 | dynargs[2] = _args[2]; 559 | return provable_query(_datasource, dynargs, _gasLimit); 560 | } 561 | 562 | function provable_query(string memory _datasource, string[4] memory _args) provableAPI internal returns (bytes32 _id) { 563 | string[] memory dynargs = new string[](4); 564 | dynargs[0] = _args[0]; 565 | dynargs[1] = _args[1]; 566 | dynargs[2] = _args[2]; 567 | dynargs[3] = _args[3]; 568 | return provable_query(_datasource, dynargs); 569 | } 570 | 571 | function provable_query(uint _timestamp, string memory _datasource, string[4] memory _args) provableAPI internal returns (bytes32 _id) { 572 | string[] memory dynargs = new string[](4); 573 | dynargs[0] = _args[0]; 574 | dynargs[1] = _args[1]; 575 | dynargs[2] = _args[2]; 576 | dynargs[3] = _args[3]; 577 | return provable_query(_timestamp, _datasource, dynargs); 578 | } 579 | 580 | function provable_query(uint _timestamp, string memory _datasource, string[4] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 581 | string[] memory dynargs = new string[](4); 582 | dynargs[0] = _args[0]; 583 | dynargs[1] = _args[1]; 584 | dynargs[2] = _args[2]; 585 | dynargs[3] = _args[3]; 586 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 587 | } 588 | 589 | function provable_query(string memory _datasource, string[4] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 590 | string[] memory dynargs = new string[](4); 591 | dynargs[0] = _args[0]; 592 | dynargs[1] = _args[1]; 593 | dynargs[2] = _args[2]; 594 | dynargs[3] = _args[3]; 595 | return provable_query(_datasource, dynargs, _gasLimit); 596 | } 597 | 598 | function provable_query(string memory _datasource, string[5] memory _args) provableAPI internal returns (bytes32 _id) { 599 | string[] memory dynargs = new string[](5); 600 | dynargs[0] = _args[0]; 601 | dynargs[1] = _args[1]; 602 | dynargs[2] = _args[2]; 603 | dynargs[3] = _args[3]; 604 | dynargs[4] = _args[4]; 605 | return provable_query(_datasource, dynargs); 606 | } 607 | 608 | function provable_query(uint _timestamp, string memory _datasource, string[5] memory _args) provableAPI internal returns (bytes32 _id) { 609 | string[] memory dynargs = new string[](5); 610 | dynargs[0] = _args[0]; 611 | dynargs[1] = _args[1]; 612 | dynargs[2] = _args[2]; 613 | dynargs[3] = _args[3]; 614 | dynargs[4] = _args[4]; 615 | return provable_query(_timestamp, _datasource, dynargs); 616 | } 617 | 618 | function provable_query(uint _timestamp, string memory _datasource, string[5] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 619 | string[] memory dynargs = new string[](5); 620 | dynargs[0] = _args[0]; 621 | dynargs[1] = _args[1]; 622 | dynargs[2] = _args[2]; 623 | dynargs[3] = _args[3]; 624 | dynargs[4] = _args[4]; 625 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 626 | } 627 | 628 | function provable_query(string memory _datasource, string[5] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 629 | string[] memory dynargs = new string[](5); 630 | dynargs[0] = _args[0]; 631 | dynargs[1] = _args[1]; 632 | dynargs[2] = _args[2]; 633 | dynargs[3] = _args[3]; 634 | dynargs[4] = _args[4]; 635 | return provable_query(_datasource, dynargs, _gasLimit); 636 | } 637 | 638 | function provable_query(string memory _datasource, bytes[] memory _argN) provableAPI internal returns (bytes32 _id) { 639 | uint price = provable.getPrice(_datasource); 640 | if (price > 1 ether + tx.gasprice * 200000) { 641 | return 0; // Unexpectedly high price 642 | } 643 | bytes memory args = ba2cbor(_argN); 644 | return provable.queryN.value(price)(0, _datasource, args); 645 | } 646 | 647 | function provable_query(uint _timestamp, string memory _datasource, bytes[] memory _argN) provableAPI internal returns (bytes32 _id) { 648 | uint price = provable.getPrice(_datasource); 649 | if (price > 1 ether + tx.gasprice * 200000) { 650 | return 0; // Unexpectedly high price 651 | } 652 | bytes memory args = ba2cbor(_argN); 653 | return provable.queryN.value(price)(_timestamp, _datasource, args); 654 | } 655 | 656 | function provable_query(uint _timestamp, string memory _datasource, bytes[] memory _argN, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 657 | uint price = provable.getPrice(_datasource, _gasLimit); 658 | if (price > 1 ether + tx.gasprice * _gasLimit) { 659 | return 0; // Unexpectedly high price 660 | } 661 | bytes memory args = ba2cbor(_argN); 662 | return provable.queryN_withGasLimit.value(price)(_timestamp, _datasource, args, _gasLimit); 663 | } 664 | 665 | function provable_query(string memory _datasource, bytes[] memory _argN, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 666 | uint price = provable.getPrice(_datasource, _gasLimit); 667 | if (price > 1 ether + tx.gasprice * _gasLimit) { 668 | return 0; // Unexpectedly high price 669 | } 670 | bytes memory args = ba2cbor(_argN); 671 | return provable.queryN_withGasLimit.value(price)(0, _datasource, args, _gasLimit); 672 | } 673 | 674 | function provable_query(string memory _datasource, bytes[1] memory _args) provableAPI internal returns (bytes32 _id) { 675 | bytes[] memory dynargs = new bytes[](1); 676 | dynargs[0] = _args[0]; 677 | return provable_query(_datasource, dynargs); 678 | } 679 | 680 | function provable_query(uint _timestamp, string memory _datasource, bytes[1] memory _args) provableAPI internal returns (bytes32 _id) { 681 | bytes[] memory dynargs = new bytes[](1); 682 | dynargs[0] = _args[0]; 683 | return provable_query(_timestamp, _datasource, dynargs); 684 | } 685 | 686 | function provable_query(uint _timestamp, string memory _datasource, bytes[1] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 687 | bytes[] memory dynargs = new bytes[](1); 688 | dynargs[0] = _args[0]; 689 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 690 | } 691 | 692 | function provable_query(string memory _datasource, bytes[1] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 693 | bytes[] memory dynargs = new bytes[](1); 694 | dynargs[0] = _args[0]; 695 | return provable_query(_datasource, dynargs, _gasLimit); 696 | } 697 | 698 | function provable_query(string memory _datasource, bytes[2] memory _args) provableAPI internal returns (bytes32 _id) { 699 | bytes[] memory dynargs = new bytes[](2); 700 | dynargs[0] = _args[0]; 701 | dynargs[1] = _args[1]; 702 | return provable_query(_datasource, dynargs); 703 | } 704 | 705 | function provable_query(uint _timestamp, string memory _datasource, bytes[2] memory _args) provableAPI internal returns (bytes32 _id) { 706 | bytes[] memory dynargs = new bytes[](2); 707 | dynargs[0] = _args[0]; 708 | dynargs[1] = _args[1]; 709 | return provable_query(_timestamp, _datasource, dynargs); 710 | } 711 | 712 | function provable_query(uint _timestamp, string memory _datasource, bytes[2] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 713 | bytes[] memory dynargs = new bytes[](2); 714 | dynargs[0] = _args[0]; 715 | dynargs[1] = _args[1]; 716 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 717 | } 718 | 719 | function provable_query(string memory _datasource, bytes[2] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 720 | bytes[] memory dynargs = new bytes[](2); 721 | dynargs[0] = _args[0]; 722 | dynargs[1] = _args[1]; 723 | return provable_query(_datasource, dynargs, _gasLimit); 724 | } 725 | 726 | function provable_query(string memory _datasource, bytes[3] memory _args) provableAPI internal returns (bytes32 _id) { 727 | bytes[] memory dynargs = new bytes[](3); 728 | dynargs[0] = _args[0]; 729 | dynargs[1] = _args[1]; 730 | dynargs[2] = _args[2]; 731 | return provable_query(_datasource, dynargs); 732 | } 733 | 734 | function provable_query(uint _timestamp, string memory _datasource, bytes[3] memory _args) provableAPI internal returns (bytes32 _id) { 735 | bytes[] memory dynargs = new bytes[](3); 736 | dynargs[0] = _args[0]; 737 | dynargs[1] = _args[1]; 738 | dynargs[2] = _args[2]; 739 | return provable_query(_timestamp, _datasource, dynargs); 740 | } 741 | 742 | function provable_query(uint _timestamp, string memory _datasource, bytes[3] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 743 | bytes[] memory dynargs = new bytes[](3); 744 | dynargs[0] = _args[0]; 745 | dynargs[1] = _args[1]; 746 | dynargs[2] = _args[2]; 747 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 748 | } 749 | 750 | function provable_query(string memory _datasource, bytes[3] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 751 | bytes[] memory dynargs = new bytes[](3); 752 | dynargs[0] = _args[0]; 753 | dynargs[1] = _args[1]; 754 | dynargs[2] = _args[2]; 755 | return provable_query(_datasource, dynargs, _gasLimit); 756 | } 757 | 758 | function provable_query(string memory _datasource, bytes[4] memory _args) provableAPI internal returns (bytes32 _id) { 759 | bytes[] memory dynargs = new bytes[](4); 760 | dynargs[0] = _args[0]; 761 | dynargs[1] = _args[1]; 762 | dynargs[2] = _args[2]; 763 | dynargs[3] = _args[3]; 764 | return provable_query(_datasource, dynargs); 765 | } 766 | 767 | function provable_query(uint _timestamp, string memory _datasource, bytes[4] memory _args) provableAPI internal returns (bytes32 _id) { 768 | bytes[] memory dynargs = new bytes[](4); 769 | dynargs[0] = _args[0]; 770 | dynargs[1] = _args[1]; 771 | dynargs[2] = _args[2]; 772 | dynargs[3] = _args[3]; 773 | return provable_query(_timestamp, _datasource, dynargs); 774 | } 775 | 776 | function provable_query(uint _timestamp, string memory _datasource, bytes[4] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 777 | bytes[] memory dynargs = new bytes[](4); 778 | dynargs[0] = _args[0]; 779 | dynargs[1] = _args[1]; 780 | dynargs[2] = _args[2]; 781 | dynargs[3] = _args[3]; 782 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 783 | } 784 | 785 | function provable_query(string memory _datasource, bytes[4] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 786 | bytes[] memory dynargs = new bytes[](4); 787 | dynargs[0] = _args[0]; 788 | dynargs[1] = _args[1]; 789 | dynargs[2] = _args[2]; 790 | dynargs[3] = _args[3]; 791 | return provable_query(_datasource, dynargs, _gasLimit); 792 | } 793 | 794 | function provable_query(string memory _datasource, bytes[5] memory _args) provableAPI internal returns (bytes32 _id) { 795 | bytes[] memory dynargs = new bytes[](5); 796 | dynargs[0] = _args[0]; 797 | dynargs[1] = _args[1]; 798 | dynargs[2] = _args[2]; 799 | dynargs[3] = _args[3]; 800 | dynargs[4] = _args[4]; 801 | return provable_query(_datasource, dynargs); 802 | } 803 | 804 | function provable_query(uint _timestamp, string memory _datasource, bytes[5] memory _args) provableAPI internal returns (bytes32 _id) { 805 | bytes[] memory dynargs = new bytes[](5); 806 | dynargs[0] = _args[0]; 807 | dynargs[1] = _args[1]; 808 | dynargs[2] = _args[2]; 809 | dynargs[3] = _args[3]; 810 | dynargs[4] = _args[4]; 811 | return provable_query(_timestamp, _datasource, dynargs); 812 | } 813 | 814 | function provable_query(uint _timestamp, string memory _datasource, bytes[5] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 815 | bytes[] memory dynargs = new bytes[](5); 816 | dynargs[0] = _args[0]; 817 | dynargs[1] = _args[1]; 818 | dynargs[2] = _args[2]; 819 | dynargs[3] = _args[3]; 820 | dynargs[4] = _args[4]; 821 | return provable_query(_timestamp, _datasource, dynargs, _gasLimit); 822 | } 823 | 824 | function provable_query(string memory _datasource, bytes[5] memory _args, uint _gasLimit) provableAPI internal returns (bytes32 _id) { 825 | bytes[] memory dynargs = new bytes[](5); 826 | dynargs[0] = _args[0]; 827 | dynargs[1] = _args[1]; 828 | dynargs[2] = _args[2]; 829 | dynargs[3] = _args[3]; 830 | dynargs[4] = _args[4]; 831 | return provable_query(_datasource, dynargs, _gasLimit); 832 | } 833 | 834 | function provable_setProof(byte _proofP) provableAPI internal { 835 | return provable.setProofType(_proofP); 836 | } 837 | 838 | 839 | function provable_cbAddress() provableAPI internal returns (address _callbackAddress) { 840 | return provable.cbAddress(); 841 | } 842 | 843 | function getCodeSize(address _addr) view internal returns (uint _size) { 844 | assembly { 845 | _size := extcodesize(_addr) 846 | } 847 | } 848 | 849 | function provable_setCustomGasPrice(uint _gasPrice) provableAPI internal { 850 | return provable.setCustomGasPrice(_gasPrice); 851 | } 852 | 853 | function provable_randomDS_getSessionPubKeyHash() provableAPI internal returns (bytes32 _sessionKeyHash) { 854 | return provable.randomDS_getSessionPubKeyHash(); 855 | } 856 | 857 | function parseAddr(string memory _a) internal pure returns (address _parsedAddress) { 858 | bytes memory tmp = bytes(_a); 859 | uint160 iaddr = 0; 860 | uint160 b1; 861 | uint160 b2; 862 | for (uint i = 2; i < 2 + 2 * 20; i += 2) { 863 | iaddr *= 256; 864 | b1 = uint160(uint8(tmp[i])); 865 | b2 = uint160(uint8(tmp[i + 1])); 866 | if ((b1 >= 97) && (b1 <= 102)) { 867 | b1 -= 87; 868 | } else if ((b1 >= 65) && (b1 <= 70)) { 869 | b1 -= 55; 870 | } else if ((b1 >= 48) && (b1 <= 57)) { 871 | b1 -= 48; 872 | } 873 | if ((b2 >= 97) && (b2 <= 102)) { 874 | b2 -= 87; 875 | } else if ((b2 >= 65) && (b2 <= 70)) { 876 | b2 -= 55; 877 | } else if ((b2 >= 48) && (b2 <= 57)) { 878 | b2 -= 48; 879 | } 880 | iaddr += (b1 * 16 + b2); 881 | } 882 | return address(iaddr); 883 | } 884 | 885 | function strCompare(string memory _a, string memory _b) internal pure returns (int _returnCode) { 886 | bytes memory a = bytes(_a); 887 | bytes memory b = bytes(_b); 888 | uint minLength = a.length; 889 | if (b.length < minLength) { 890 | minLength = b.length; 891 | } 892 | for (uint i = 0; i < minLength; i ++) { 893 | if (a[i] < b[i]) { 894 | return -1; 895 | } else if (a[i] > b[i]) { 896 | return 1; 897 | } 898 | } 899 | if (a.length < b.length) { 900 | return -1; 901 | } else if (a.length > b.length) { 902 | return 1; 903 | } else { 904 | return 0; 905 | } 906 | } 907 | 908 | function indexOf(string memory _haystack, string memory _needle) internal pure returns (int _returnCode) { 909 | bytes memory h = bytes(_haystack); 910 | bytes memory n = bytes(_needle); 911 | if (h.length < 1 || n.length < 1 || (n.length > h.length)) { 912 | return -1; 913 | } else if (h.length > (2 ** 128 - 1)) { 914 | return -1; 915 | } else { 916 | uint subindex = 0; 917 | for (uint i = 0; i < h.length; i++) { 918 | if (h[i] == n[0]) { 919 | subindex = 1; 920 | while(subindex < n.length && (i + subindex) < h.length && h[i + subindex] == n[subindex]) { 921 | subindex++; 922 | } 923 | if (subindex == n.length) { 924 | return int(i); 925 | } 926 | } 927 | } 928 | return -1; 929 | } 930 | } 931 | 932 | function strConcat(string memory _a, string memory _b) internal pure returns (string memory _concatenatedString) { 933 | return strConcat(_a, _b, "", "", ""); 934 | } 935 | 936 | function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory _concatenatedString) { 937 | return strConcat(_a, _b, _c, "", ""); 938 | } 939 | 940 | function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory _concatenatedString) { 941 | return strConcat(_a, _b, _c, _d, ""); 942 | } 943 | 944 | function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory _concatenatedString) { 945 | bytes memory _ba = bytes(_a); 946 | bytes memory _bb = bytes(_b); 947 | bytes memory _bc = bytes(_c); 948 | bytes memory _bd = bytes(_d); 949 | bytes memory _be = bytes(_e); 950 | string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); 951 | bytes memory babcde = bytes(abcde); 952 | uint k = 0; 953 | uint i = 0; 954 | for (i = 0; i < _ba.length; i++) { 955 | babcde[k++] = _ba[i]; 956 | } 957 | for (i = 0; i < _bb.length; i++) { 958 | babcde[k++] = _bb[i]; 959 | } 960 | for (i = 0; i < _bc.length; i++) { 961 | babcde[k++] = _bc[i]; 962 | } 963 | for (i = 0; i < _bd.length; i++) { 964 | babcde[k++] = _bd[i]; 965 | } 966 | for (i = 0; i < _be.length; i++) { 967 | babcde[k++] = _be[i]; 968 | } 969 | return string(babcde); 970 | } 971 | 972 | function safeParseInt(string memory _a) internal pure returns (uint _parsedInt) { 973 | return safeParseInt(_a, 0); 974 | } 975 | 976 | function safeParseInt(string memory _a, uint _b) internal pure returns (uint _parsedInt) { 977 | bytes memory bresult = bytes(_a); 978 | uint mint = 0; 979 | bool decimals = false; 980 | for (uint i = 0; i < bresult.length; i++) { 981 | if ((uint(uint8(bresult[i])) >= 48) && (uint(uint8(bresult[i])) <= 57)) { 982 | if (decimals) { 983 | if (_b == 0) break; 984 | else _b--; 985 | } 986 | mint *= 10; 987 | mint += uint(uint8(bresult[i])) - 48; 988 | } else if (uint(uint8(bresult[i])) == 46) { 989 | require(!decimals, 'More than one decimal encountered in string!'); 990 | decimals = true; 991 | } else { 992 | revert("Non-numeral character encountered in string!"); 993 | } 994 | } 995 | if (_b > 0) { 996 | mint *= 10 ** _b; 997 | } 998 | return mint; 999 | } 1000 | 1001 | function parseInt(string memory _a) internal pure returns (uint _parsedInt) { 1002 | return parseInt(_a, 0); 1003 | } 1004 | 1005 | function parseInt(string memory _a, uint _b) internal pure returns (uint _parsedInt) { 1006 | bytes memory bresult = bytes(_a); 1007 | uint mint = 0; 1008 | bool decimals = false; 1009 | for (uint i = 0; i < bresult.length; i++) { 1010 | if ((uint(uint8(bresult[i])) >= 48) && (uint(uint8(bresult[i])) <= 57)) { 1011 | if (decimals) { 1012 | if (_b == 0) { 1013 | break; 1014 | } else { 1015 | _b--; 1016 | } 1017 | } 1018 | mint *= 10; 1019 | mint += uint(uint8(bresult[i])) - 48; 1020 | } else if (uint(uint8(bresult[i])) == 46) { 1021 | decimals = true; 1022 | } 1023 | } 1024 | if (_b > 0) { 1025 | mint *= 10 ** _b; 1026 | } 1027 | return mint; 1028 | } 1029 | 1030 | function uint2str(uint _i) internal pure returns (string memory _uintAsString) { 1031 | if (_i == 0) { 1032 | return "0"; 1033 | } 1034 | uint j = _i; 1035 | uint len; 1036 | while (j != 0) { 1037 | len++; 1038 | j /= 10; 1039 | } 1040 | bytes memory bstr = new bytes(len); 1041 | uint k = len - 1; 1042 | while (_i != 0) { 1043 | bstr[k--] = byte(uint8(48 + _i % 10)); 1044 | _i /= 10; 1045 | } 1046 | return string(bstr); 1047 | } 1048 | 1049 | function stra2cbor(string[] memory _arr) internal pure returns (bytes memory _cborEncoding) { 1050 | safeMemoryCleaner(); 1051 | Buffer.buffer memory buf; 1052 | Buffer.init(buf, 1024); 1053 | buf.startArray(); 1054 | for (uint i = 0; i < _arr.length; i++) { 1055 | buf.encodeString(_arr[i]); 1056 | } 1057 | buf.endSequence(); 1058 | return buf.buf; 1059 | } 1060 | 1061 | function ba2cbor(bytes[] memory _arr) internal pure returns (bytes memory _cborEncoding) { 1062 | safeMemoryCleaner(); 1063 | Buffer.buffer memory buf; 1064 | Buffer.init(buf, 1024); 1065 | buf.startArray(); 1066 | for (uint i = 0; i < _arr.length; i++) { 1067 | buf.encodeBytes(_arr[i]); 1068 | } 1069 | buf.endSequence(); 1070 | return buf.buf; 1071 | } 1072 | 1073 | function provable_newRandomDSQuery(uint _delay, uint _nbytes, uint _customGasLimit) internal returns (bytes32 _queryId) { 1074 | require((_nbytes > 0) && (_nbytes <= 32)); 1075 | _delay *= 10; // Convert from seconds to ledger timer ticks 1076 | bytes memory nbytes = new bytes(1); 1077 | nbytes[0] = byte(uint8(_nbytes)); 1078 | bytes memory unonce = new bytes(32); 1079 | bytes memory sessionKeyHash = new bytes(32); 1080 | bytes32 sessionKeyHash_bytes32 = provable_randomDS_getSessionPubKeyHash(); 1081 | assembly { 1082 | mstore(unonce, 0x20) 1083 | /* 1084 | The following variables can be relaxed. 1085 | Check the relaxed random contract at https://github.com/oraclize/ethereum-examples 1086 | for an idea on how to override and replace commit hash variables. 1087 | */ 1088 | mstore(add(unonce, 0x20), xor(blockhash(sub(number, 1)), xor(coinbase, timestamp))) 1089 | mstore(sessionKeyHash, 0x20) 1090 | mstore(add(sessionKeyHash, 0x20), sessionKeyHash_bytes32) 1091 | } 1092 | bytes memory delay = new bytes(32); 1093 | assembly { 1094 | mstore(add(delay, 0x20), _delay) 1095 | } 1096 | bytes memory delay_bytes8 = new bytes(8); 1097 | copyBytes(delay, 24, 8, delay_bytes8, 0); 1098 | bytes[4] memory args = [unonce, nbytes, sessionKeyHash, delay]; 1099 | bytes32 queryId = provable_query("random", args, _customGasLimit); 1100 | bytes memory delay_bytes8_left = new bytes(8); 1101 | assembly { 1102 | let x := mload(add(delay_bytes8, 0x20)) 1103 | mstore8(add(delay_bytes8_left, 0x27), div(x, 0x100000000000000000000000000000000000000000000000000000000000000)) 1104 | mstore8(add(delay_bytes8_left, 0x26), div(x, 0x1000000000000000000000000000000000000000000000000000000000000)) 1105 | mstore8(add(delay_bytes8_left, 0x25), div(x, 0x10000000000000000000000000000000000000000000000000000000000)) 1106 | mstore8(add(delay_bytes8_left, 0x24), div(x, 0x100000000000000000000000000000000000000000000000000000000)) 1107 | mstore8(add(delay_bytes8_left, 0x23), div(x, 0x1000000000000000000000000000000000000000000000000000000)) 1108 | mstore8(add(delay_bytes8_left, 0x22), div(x, 0x10000000000000000000000000000000000000000000000000000)) 1109 | mstore8(add(delay_bytes8_left, 0x21), div(x, 0x100000000000000000000000000000000000000000000000000)) 1110 | mstore8(add(delay_bytes8_left, 0x20), div(x, 0x1000000000000000000000000000000000000000000000000)) 1111 | } 1112 | provable_randomDS_setCommitment(queryId, keccak256(abi.encodePacked(delay_bytes8_left, args[1], sha256(args[0]), args[2]))); 1113 | return queryId; 1114 | } 1115 | 1116 | function provable_randomDS_setCommitment(bytes32 _queryId, bytes32 _commitment) internal { 1117 | provable_randomDS_args[_queryId] = _commitment; 1118 | } 1119 | 1120 | function verifySig(bytes32 _tosignh, bytes memory _dersig, bytes memory _pubkey) internal returns (bool _sigVerified) { 1121 | bool sigok; 1122 | address signer; 1123 | bytes32 sigr; 1124 | bytes32 sigs; 1125 | bytes memory sigr_ = new bytes(32); 1126 | uint offset = 4 + (uint(uint8(_dersig[3])) - 0x20); 1127 | sigr_ = copyBytes(_dersig, offset, 32, sigr_, 0); 1128 | bytes memory sigs_ = new bytes(32); 1129 | offset += 32 + 2; 1130 | sigs_ = copyBytes(_dersig, offset + (uint(uint8(_dersig[offset - 1])) - 0x20), 32, sigs_, 0); 1131 | assembly { 1132 | sigr := mload(add(sigr_, 32)) 1133 | sigs := mload(add(sigs_, 32)) 1134 | } 1135 | (sigok, signer) = safer_ecrecover(_tosignh, 27, sigr, sigs); 1136 | if (address(uint160(uint256(keccak256(_pubkey)))) == signer) { 1137 | return true; 1138 | } else { 1139 | (sigok, signer) = safer_ecrecover(_tosignh, 28, sigr, sigs); 1140 | return (address(uint160(uint256(keccak256(_pubkey)))) == signer); 1141 | } 1142 | } 1143 | 1144 | function provable_randomDS_proofVerify__sessionKeyValidity(bytes memory _proof, uint _sig2offset) internal returns (bool _proofVerified) { 1145 | bool sigok; 1146 | // Random DS Proof Step 6: Verify the attestation signature, APPKEY1 must sign the sessionKey from the correct ledger app (CODEHASH) 1147 | bytes memory sig2 = new bytes(uint(uint8(_proof[_sig2offset + 1])) + 2); 1148 | copyBytes(_proof, _sig2offset, sig2.length, sig2, 0); 1149 | bytes memory appkey1_pubkey = new bytes(64); 1150 | copyBytes(_proof, 3 + 1, 64, appkey1_pubkey, 0); 1151 | bytes memory tosign2 = new bytes(1 + 65 + 32); 1152 | tosign2[0] = byte(uint8(1)); //role 1153 | copyBytes(_proof, _sig2offset - 65, 65, tosign2, 1); 1154 | bytes memory CODEHASH = hex"fd94fa71bc0ba10d39d464d0d8f465efeef0a2764e3887fcc9df41ded20f505c"; 1155 | copyBytes(CODEHASH, 0, 32, tosign2, 1 + 65); 1156 | sigok = verifySig(sha256(tosign2), sig2, appkey1_pubkey); 1157 | if (!sigok) { 1158 | return false; 1159 | } 1160 | // Random DS Proof Step 7: Verify the APPKEY1 provenance (must be signed by Ledger) 1161 | bytes memory LEDGERKEY = hex"7fb956469c5c9b89840d55b43537e66a98dd4811ea0a27224272c2e5622911e8537a2f8e86a46baec82864e98dd01e9ccc2f8bc5dfc9cbe5a91a290498dd96e4"; 1162 | bytes memory tosign3 = new bytes(1 + 65); 1163 | tosign3[0] = 0xFE; 1164 | copyBytes(_proof, 3, 65, tosign3, 1); 1165 | bytes memory sig3 = new bytes(uint(uint8(_proof[3 + 65 + 1])) + 2); 1166 | copyBytes(_proof, 3 + 65, sig3.length, sig3, 0); 1167 | sigok = verifySig(sha256(tosign3), sig3, LEDGERKEY); 1168 | return sigok; 1169 | } 1170 | 1171 | function provable_randomDS_proofVerify__returnCode(bytes32 _queryId, string memory _result, bytes memory _proof) internal returns (uint8 _returnCode) { 1172 | // Random DS Proof Step 1: The prefix has to match 'LP\x01' (Ledger Proof version 1) 1173 | if ((_proof[0] != "L") || (_proof[1] != "P") || (uint8(_proof[2]) != uint8(1))) { 1174 | return 1; 1175 | } 1176 | bool proofVerified = provable_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), provable_getNetworkName()); 1177 | if (!proofVerified) { 1178 | return 2; 1179 | } 1180 | return 0; 1181 | } 1182 | 1183 | function matchBytes32Prefix(bytes32 _content, bytes memory _prefix, uint _nRandomBytes) internal pure returns (bool _matchesPrefix) { 1184 | bool match_ = true; 1185 | require(_prefix.length == _nRandomBytes); 1186 | for (uint256 i = 0; i< _nRandomBytes; i++) { 1187 | if (_content[i] != _prefix[i]) { 1188 | match_ = false; 1189 | } 1190 | } 1191 | return match_; 1192 | } 1193 | 1194 | function provable_randomDS_proofVerify__main(bytes memory _proof, bytes32 _queryId, bytes memory _result, string memory _contextName) internal returns (bool _proofVerified) { 1195 | // Random DS Proof Step 2: The unique keyhash has to match with the sha256 of (context name + _queryId) 1196 | uint ledgerProofLength = 3 + 65 + (uint(uint8(_proof[3 + 65 + 1])) + 2) + 32; 1197 | bytes memory keyhash = new bytes(32); 1198 | copyBytes(_proof, ledgerProofLength, 32, keyhash, 0); 1199 | if (!(keccak256(keyhash) == keccak256(abi.encodePacked(sha256(abi.encodePacked(_contextName, _queryId)))))) { 1200 | return false; 1201 | } 1202 | bytes memory sig1 = new bytes(uint(uint8(_proof[ledgerProofLength + (32 + 8 + 1 + 32) + 1])) + 2); 1203 | copyBytes(_proof, ledgerProofLength + (32 + 8 + 1 + 32), sig1.length, sig1, 0); 1204 | // Random DS Proof Step 3: We assume sig1 is valid (it will be verified during step 5) and we verify if '_result' is the _prefix of sha256(sig1) 1205 | if (!matchBytes32Prefix(sha256(sig1), _result, uint(uint8(_proof[ledgerProofLength + 32 + 8])))) { 1206 | return false; 1207 | } 1208 | // Random DS Proof Step 4: Commitment match verification, keccak256(delay, nbytes, unonce, sessionKeyHash) == commitment in storage. 1209 | // This is to verify that the computed args match with the ones specified in the query. 1210 | bytes memory commitmentSlice1 = new bytes(8 + 1 + 32); 1211 | copyBytes(_proof, ledgerProofLength + 32, 8 + 1 + 32, commitmentSlice1, 0); 1212 | bytes memory sessionPubkey = new bytes(64); 1213 | uint sig2offset = ledgerProofLength + 32 + (8 + 1 + 32) + sig1.length + 65; 1214 | copyBytes(_proof, sig2offset - 64, 64, sessionPubkey, 0); 1215 | bytes32 sessionPubkeyHash = sha256(sessionPubkey); 1216 | if (provable_randomDS_args[_queryId] == keccak256(abi.encodePacked(commitmentSlice1, sessionPubkeyHash))) { //unonce, nbytes and sessionKeyHash match 1217 | delete provable_randomDS_args[_queryId]; 1218 | } else return false; 1219 | // Random DS Proof Step 5: Validity verification for sig1 (keyhash and args signed with the sessionKey) 1220 | bytes memory tosign1 = new bytes(32 + 8 + 1 + 32); 1221 | copyBytes(_proof, ledgerProofLength, 32 + 8 + 1 + 32, tosign1, 0); 1222 | if (!verifySig(sha256(tosign1), sig1, sessionPubkey)) { 1223 | return false; 1224 | } 1225 | // Verify if sessionPubkeyHash was verified already, if not.. let's do it! 1226 | if (!provable_randomDS_sessionKeysHashVerified[sessionPubkeyHash]) { 1227 | provable_randomDS_sessionKeysHashVerified[sessionPubkeyHash] = provable_randomDS_proofVerify__sessionKeyValidity(_proof, sig2offset); 1228 | } 1229 | return provable_randomDS_sessionKeysHashVerified[sessionPubkeyHash]; 1230 | } 1231 | /* 1232 | The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license 1233 | */ 1234 | function copyBytes(bytes memory _from, uint _fromOffset, uint _length, bytes memory _to, uint _toOffset) internal pure returns (bytes memory _copiedBytes) { 1235 | uint minLength = _length + _toOffset; 1236 | require(_to.length >= minLength); // Buffer too small. Should be a better way? 1237 | uint i = 32 + _fromOffset; // NOTE: the offset 32 is added to skip the `size` field of both bytes variables 1238 | uint j = 32 + _toOffset; 1239 | while (i < (32 + _fromOffset + _length)) { 1240 | assembly { 1241 | let tmp := mload(add(_from, i)) 1242 | mstore(add(_to, j), tmp) 1243 | } 1244 | i += 32; 1245 | j += 32; 1246 | } 1247 | return _to; 1248 | } 1249 | /* 1250 | The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license 1251 | Duplicate Solidity's ecrecover, but catching the CALL return value 1252 | */ 1253 | function safer_ecrecover(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal returns (bool _success, address _recoveredAddress) { 1254 | /* 1255 | We do our own memory management here. Solidity uses memory offset 1256 | 0x40 to store the current end of memory. We write past it (as 1257 | writes are memory extensions), but don't update the offset so 1258 | Solidity will reuse it. The memory used here is only needed for 1259 | this context. 1260 | FIXME: inline assembly can't access return values 1261 | */ 1262 | bool ret; 1263 | address addr; 1264 | assembly { 1265 | let size := mload(0x40) 1266 | mstore(size, _hash) 1267 | mstore(add(size, 32), _v) 1268 | mstore(add(size, 64), _r) 1269 | mstore(add(size, 96), _s) 1270 | ret := call(3000, 1, 0, size, 128, size, 32) // NOTE: we can reuse the request memory because we deal with the return code. 1271 | addr := mload(size) 1272 | } 1273 | return (ret, addr); 1274 | } 1275 | /* 1276 | The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license 1277 | */ 1278 | function ecrecovery(bytes32 _hash, bytes memory _sig) internal returns (bool _success, address _recoveredAddress) { 1279 | bytes32 r; 1280 | bytes32 s; 1281 | uint8 v; 1282 | if (_sig.length != 65) { 1283 | return (false, address(0)); 1284 | } 1285 | /* 1286 | The signature format is a compact form of: 1287 | {bytes32 r}{bytes32 s}{uint8 v} 1288 | Compact means, uint8 is not padded to 32 bytes. 1289 | */ 1290 | assembly { 1291 | r := mload(add(_sig, 32)) 1292 | s := mload(add(_sig, 64)) 1293 | /* 1294 | Here we are loading the last 32 bytes. We exploit the fact that 1295 | 'mload' will pad with zeroes if we overread. 1296 | There is no 'mload8' to do this, but that would be nicer. 1297 | */ 1298 | v := byte(0, mload(add(_sig, 96))) 1299 | /* 1300 | Alternative solution: 1301 | 'byte' is not working due to the Solidity parser, so lets 1302 | use the second best option, 'and' 1303 | v := and(mload(add(_sig, 65)), 255) 1304 | */ 1305 | } 1306 | /* 1307 | albeit non-transactional signatures are not specified by the YP, one would expect it 1308 | to match the YP range of [27, 28] 1309 | geth uses [0, 1] and some clients have followed. This might change, see: 1310 | https://github.com/ethereum/go-ethereum/issues/2053 1311 | */ 1312 | if (v < 27) { 1313 | v += 27; 1314 | } 1315 | if (v != 27 && v != 28) { 1316 | return (false, address(0)); 1317 | } 1318 | return safer_ecrecover(_hash, v, r, s); 1319 | } 1320 | 1321 | function safeMemoryCleaner() internal pure { 1322 | assembly { 1323 | let fmem := mload(0x40) 1324 | codecopy(fmem, codesize, sub(msize, fmem)) 1325 | } 1326 | } 1327 | } 1328 | // -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const Coinflip = artifacts.require("Coinflip"); 2 | 3 | module.exports = function (deployer, network, accounts) { 4 | deployer.deploy(Coinflip,{value: web3.utils.toWei("1", "ether"), from: accounts[0]}); 5 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flip-contract", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@chainlink/contracts": "^0.0.11", 14 | "@openzeppelin/contracts": "^4.5.0", 15 | "dotenv": "^16.0.0", 16 | "truffle": "^5.5.6", 17 | "truffle-plugin-verify": "^0.5.24" 18 | }, 19 | "devDependencies": { 20 | "@truffle/hdwallet-provider": "^2.0.4" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crypt0legendx/Coinflip-Contract-ProvableAPI/91c6077b5f0f80b0ebcc9d153673e84e2b92a408/test/.gitkeep -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const privateKeys = process.env.PRIVATE_KEYS || "" 3 | const HDWalletProvider = require('@truffle/hdwallet-provider'); 4 | module.exports = { 5 | networks: { 6 | development: { 7 | host: "127.0.0.1", // Localhost (default: none) 8 | port: 8545, // Standard Ethereum port (default: none) 9 | network_id: "*", // Any network (default: none) 10 | }, 11 | matic: { 12 | provider: () => new HDWalletProvider( 13 | privateKeys.split(','), 14 | `https://rpc-mumbai.maticvigil.com` 15 | ), 16 | network_id: 80001, 17 | confirmations: 2, 18 | timeoutBlocks: 200, 19 | skipDryRun: true 20 | }, 21 | rinkeby: { 22 | provider: () => new HDWalletProvider( 23 | privateKeys.split(','), 24 | `https://rinkeby.infura.io/v3/23b8935c1649490bb448e80796e96581` 25 | ), 26 | network_id: 4, 27 | confirmations: 2, 28 | timeoutBlocks: 200, 29 | skipDryRun: true 30 | }, 31 | }, 32 | 33 | // Set default mocha options here, use special reporters etc. 34 | mocha: { 35 | // timeout: 100000 36 | }, 37 | 38 | //Set custom directory 39 | // contracts_directory: './src/contracts/', 40 | // contracts_build_directory: './src/abis/', 41 | 42 | // Configure your compilers 43 | compilers: { 44 | solc: { 45 | version: "0.6.6", // Fetch exact version from solc-bin (default: truffle's version) 46 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 47 | // settings: { // See the solidity docs for advice about optimization and evmVersion 48 | // optimizer: { 49 | // enabled: false, 50 | // runs: 200 51 | // }, 52 | // evmVersion: "byzantium" 53 | // } 54 | } 55 | }, 56 | 57 | plugins: [ 58 | 'truffle-plugin-verify' 59 | ], 60 | 61 | api_keys: { 62 | polygonscan: process.env.POLYGONSCAN_API_KEY, 63 | etherscan: process.env.RINKEBY_API_KEY 64 | }, 65 | 66 | db: { 67 | enabled: false, 68 | // host: "127.0.0.1", 69 | // adapter: { 70 | // name: "sqlite", 71 | // settings: { 72 | // directory: ".db" 73 | // } 74 | // } 75 | } 76 | }; 77 | --------------------------------------------------------------------------------