diff --git a/Coinprice.sol b/Coinprice.sol new file mode 100644 index 0000000..f0dee45 --- /dev/null +++ b/Coinprice.sol @@ -0,0 +1,42 @@ +pragma solidity ^0.4.20; +/* + Import the Oraclize contract + + Outside of Remix, direct imports from GitHub may not be supported. + Instead, use a local import or just paste the Oraclize code in directly +*/ +import "./OraclizeI.sol"; + +contract Coinprice is usingOraclize { + + // Define variables + uint public USDPrice; // number obtained from random.org + + // Constructor + function Template() public { + // do any setup here + } + + // Query Oraclize to get random number + function getPriceOfEther() public payable { + // require ETH to cover callback gas costs + require(msg.value >= 0.004 ether); // 200,000 gas * 20 Gwei = 0.004 ETH + + // send query + bytes32 queryId = oraclize_query( + "nested", + "[URL] ['json(https://api.coinmarketcap.com/v2/ticker/1027/).data.quotes.USD.price']" + ); + } + + // Callback function for Oraclize once it retreives the data + function __callback(bytes32 queryId, string result, bytes proof) public { + // only allow Oraclize to call this function + require(msg.sender == oraclize_cbAddress()); + + // set random number, result is of the form: [268] + // if we also returned serialNumber, form would be "[3008768, [268]]" + USDPrice = parseInt(result); + } + +} diff --git a/OraclizeI.sol b/OraclizeI.sol new file mode 100644 index 0000000..5e4cd8e --- /dev/null +++ b/OraclizeI.sol @@ -0,0 +1,1230 @@ +// +/* +Copyright (c) 2015-2016 Oraclize SRL +Copyright (c) 2016 Oraclize LTD + + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + + + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// This api is currently targeted at 0.4.18, please import oraclizeAPI_pre0.4.sol or oraclizeAPI_0.4 where necessary + +pragma solidity >=0.4.18;// Incompatible compiler version... please select one stated within pragma solidity or use different oraclizeAPI version + +contract OraclizeI { + address public cbAddress; + function query(uint _timestamp, string _datasource, string _arg) external payable returns (bytes32 _id); + function query_withGasLimit(uint _timestamp, string _datasource, string _arg, uint _gaslimit) external payable returns (bytes32 _id); + function query2(uint _timestamp, string _datasource, string _arg1, string _arg2) public payable returns (bytes32 _id); + function query2_withGasLimit(uint _timestamp, string _datasource, string _arg1, string _arg2, uint _gaslimit) external payable returns (bytes32 _id); + function queryN(uint _timestamp, string _datasource, bytes _argN) public payable returns (bytes32 _id); + function queryN_withGasLimit(uint _timestamp, string _datasource, bytes _argN, uint _gaslimit) external payable returns (bytes32 _id); + function getPrice(string _datasource) public returns (uint _dsprice); + function getPrice(string _datasource, uint gaslimit) public returns (uint _dsprice); + function setProofType(byte _proofType) external; + function setCustomGasPrice(uint _gasPrice) external; + function randomDS_getSessionPubKeyHash() external constant returns(bytes32); +} + +contract OraclizeAddrResolverI { + function getAddress() public returns (address _addr); +} + +/* +Begin solidity-cborutils + +https://github.com/smartcontractkit/solidity-cborutils + +MIT License + +Copyright (c) 2018 SmartContract ChainLink, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +library Buffer { + struct buffer { + bytes buf; + uint capacity; + } + + function init(buffer memory buf, uint _capacity) internal pure { + uint capacity = _capacity; + if(capacity % 32 != 0) capacity += 32 - (capacity % 32); + // Allocate space for the buffer data + buf.capacity = capacity; + assembly { + let ptr := mload(0x40) + mstore(buf, ptr) + mstore(ptr, 0) + mstore(0x40, add(ptr, capacity)) + } + } + + function resize(buffer memory buf, uint capacity) private pure { + bytes memory oldbuf = buf.buf; + init(buf, capacity); + append(buf, oldbuf); + } + + function max(uint a, uint b) private pure returns(uint) { + if(a > b) { + return a; + } + return b; + } + + /** + * @dev Appends a byte array to the end of the buffer. Resizes if doing so + * would exceed the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer. + */ + function append(buffer memory buf, bytes data) internal pure returns(buffer memory) { + if(data.length + buf.buf.length > buf.capacity) { + resize(buf, max(buf.capacity, data.length) * 2); + } + + uint dest; + uint src; + uint len = data.length; + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Length of existing buffer data + let buflen := mload(bufptr) + // Start address = buffer address + buffer length + sizeof(buffer length) + dest := add(add(bufptr, buflen), 32) + // Update buffer length + mstore(bufptr, add(buflen, mload(data))) + src := add(data, 32) + } + + // Copy word-length chunks while possible + for(; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + // Copy remaining bytes + uint mask = 256 ** (32 - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + + return buf; + } + + /** + * @dev Appends a byte to the end of the buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer. + */ + function append(buffer memory buf, uint8 data) internal pure { + if(buf.buf.length + 1 > buf.capacity) { + resize(buf, buf.capacity * 2); + } + + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Length of existing buffer data + let buflen := mload(bufptr) + // Address = buffer address + buffer length + sizeof(buffer length) + let dest := add(add(bufptr, buflen), 32) + mstore8(dest, data) + // Update buffer length + mstore(bufptr, add(buflen, 1)) + } + } + + /** + * @dev Appends a byte to the end of the buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer. + */ + function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { + if(len + buf.buf.length > buf.capacity) { + resize(buf, max(buf.capacity, len) * 2); + } + + uint mask = 256 ** len - 1; + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Length of existing buffer data + let buflen := mload(bufptr) + // Address = buffer address + buffer length + sizeof(buffer length) + len + let dest := add(add(bufptr, buflen), len) + mstore(dest, or(and(mload(dest), not(mask)), data)) + // Update buffer length + mstore(bufptr, add(buflen, len)) + } + return buf; + } +} + +library CBOR { + using Buffer for Buffer.buffer; + + uint8 private constant MAJOR_TYPE_INT = 0; + uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; + uint8 private constant MAJOR_TYPE_BYTES = 2; + uint8 private constant MAJOR_TYPE_STRING = 3; + uint8 private constant MAJOR_TYPE_ARRAY = 4; + uint8 private constant MAJOR_TYPE_MAP = 5; + uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; + + function encodeType(Buffer.buffer memory buf, uint8 major, uint value) private pure { + if(value <= 23) { + buf.append(uint8((major << 5) | value)); + } else if(value <= 0xFF) { + buf.append(uint8((major << 5) | 24)); + buf.appendInt(value, 1); + } else if(value <= 0xFFFF) { + buf.append(uint8((major << 5) | 25)); + buf.appendInt(value, 2); + } else if(value <= 0xFFFFFFFF) { + buf.append(uint8((major << 5) | 26)); + buf.appendInt(value, 4); + } else if(value <= 0xFFFFFFFFFFFFFFFF) { + buf.append(uint8((major << 5) | 27)); + buf.appendInt(value, 8); + } + } + + function encodeIndefiniteLengthType(Buffer.buffer memory buf, uint8 major) private pure { + buf.append(uint8((major << 5) | 31)); + } + + function encodeUInt(Buffer.buffer memory buf, uint value) internal pure { + encodeType(buf, MAJOR_TYPE_INT, value); + } + + function encodeInt(Buffer.buffer memory buf, int value) internal pure { + if(value >= 0) { + encodeType(buf, MAJOR_TYPE_INT, uint(value)); + } else { + encodeType(buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - value)); + } + } + + function encodeBytes(Buffer.buffer memory buf, bytes value) internal pure { + encodeType(buf, MAJOR_TYPE_BYTES, value.length); + buf.append(value); + } + + function encodeString(Buffer.buffer memory buf, string value) internal pure { + encodeType(buf, MAJOR_TYPE_STRING, bytes(value).length); + buf.append(bytes(value)); + } + + function startArray(Buffer.buffer memory buf) internal pure { + encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); + } + + function startMap(Buffer.buffer memory buf) internal pure { + encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); + } + + function endSequence(Buffer.buffer memory buf) internal pure { + encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); + } +} + +/* +End solidity-cborutils + */ + +contract usingOraclize { + uint constant day = 60*60*24; + uint constant week = 60*60*24*7; + uint constant month = 60*60*24*30; + byte constant proofType_NONE = 0x00; + byte constant proofType_TLSNotary = 0x10; + byte constant proofType_Ledger = 0x30; + byte constant proofType_Android = 0x40; + byte constant proofType_Native = 0xF0; + byte constant proofStorage_IPFS = 0x01; + uint8 constant networkID_auto = 0; + uint8 constant networkID_mainnet = 1; + uint8 constant networkID_testnet = 2; + uint8 constant networkID_morden = 2; + uint8 constant networkID_consensys = 161; + + OraclizeAddrResolverI OAR; + + OraclizeI oraclize; + modifier oraclizeAPI { + if((address(OAR)==0)||(getCodeSize(address(OAR))==0)) + oraclize_setNetwork(networkID_auto); + + if(address(oraclize) != OAR.getAddress()) + oraclize = OraclizeI(OAR.getAddress()); + + _; + } + modifier coupon(string code){ + oraclize = OraclizeI(OAR.getAddress()); + _; + } + + function oraclize_setNetwork(uint8 networkID) internal returns(bool){ + return oraclize_setNetwork(); + networkID; // silence the warning and remain backwards compatible + } + function oraclize_setNetwork() internal returns(bool){ + if (getCodeSize(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed)>0){ //mainnet + OAR = OraclizeAddrResolverI(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed); + oraclize_setNetworkName("eth_mainnet"); + return true; + } + if (getCodeSize(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1)>0){ //ropsten testnet + OAR = OraclizeAddrResolverI(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1); + oraclize_setNetworkName("eth_ropsten3"); + return true; + } + if (getCodeSize(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e)>0){ //kovan testnet + OAR = OraclizeAddrResolverI(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e); + oraclize_setNetworkName("eth_kovan"); + return true; + } + if (getCodeSize(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48)>0){ //rinkeby testnet + OAR = OraclizeAddrResolverI(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48); + oraclize_setNetworkName("eth_rinkeby"); + return true; + } + if (getCodeSize(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475)>0){ //ethereum-bridge + OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475); + return true; + } + if (getCodeSize(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF)>0){ //ether.camp ide + OAR = OraclizeAddrResolverI(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF); + return true; + } + if (getCodeSize(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA)>0){ //browser-solidity + OAR = OraclizeAddrResolverI(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA); + return true; + } + return false; + } + + function __callback(bytes32 myid, string result) public { + __callback(myid, result, new bytes(0)); + } + function __callback(bytes32 myid, string result, bytes proof) public { + return; + myid; result; proof; // Silence compiler warnings + } + + function oraclize_getPrice(string datasource) oraclizeAPI internal returns (uint){ + return oraclize.getPrice(datasource); + } + + function oraclize_getPrice(string datasource, uint gaslimit) oraclizeAPI internal returns (uint){ + return oraclize.getPrice(datasource, gaslimit); + } + + function oraclize_query(string datasource, string arg) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + return oraclize.query.value(price)(0, datasource, arg); + } + function oraclize_query(uint timestamp, string datasource, string arg) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + return oraclize.query.value(price)(timestamp, datasource, arg); + } + function oraclize_query(uint timestamp, string datasource, string arg, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + return oraclize.query_withGasLimit.value(price)(timestamp, datasource, arg, gaslimit); + } + function oraclize_query(string datasource, string arg, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + return oraclize.query_withGasLimit.value(price)(0, datasource, arg, gaslimit); + } + function oraclize_query(string datasource, string arg1, string arg2) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + return oraclize.query2.value(price)(0, datasource, arg1, arg2); + } + function oraclize_query(uint timestamp, string datasource, string arg1, string arg2) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + return oraclize.query2.value(price)(timestamp, datasource, arg1, arg2); + } + function oraclize_query(uint timestamp, string datasource, string arg1, string arg2, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + return oraclize.query2_withGasLimit.value(price)(timestamp, datasource, arg1, arg2, gaslimit); + } + function oraclize_query(string datasource, string arg1, string arg2, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + return oraclize.query2_withGasLimit.value(price)(0, datasource, arg1, arg2, gaslimit); + } + function oraclize_query(string datasource, string[] argN) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + bytes memory args = stra2cbor(argN); + return oraclize.queryN.value(price)(0, datasource, args); + } + function oraclize_query(uint timestamp, string datasource, string[] argN) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + bytes memory args = stra2cbor(argN); + return oraclize.queryN.value(price)(timestamp, datasource, args); + } + function oraclize_query(uint timestamp, string datasource, string[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + bytes memory args = stra2cbor(argN); + return oraclize.queryN_withGasLimit.value(price)(timestamp, datasource, args, gaslimit); + } + function oraclize_query(string datasource, string[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + bytes memory args = stra2cbor(argN); + return oraclize.queryN_withGasLimit.value(price)(0, datasource, args, gaslimit); + } + function oraclize_query(string datasource, string[1] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](1); + dynargs[0] = args[0]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[1] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](1); + dynargs[0] = args[0]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](1); + dynargs[0] = args[0]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, string[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](1); + dynargs[0] = args[0]; + return oraclize_query(datasource, dynargs, gaslimit); + } + + function oraclize_query(string datasource, string[2] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[2] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, string[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, string[3] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[3] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, string[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(datasource, dynargs, gaslimit); + } + + function oraclize_query(string datasource, string[4] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[4] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, string[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, string[5] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[5] args) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, string[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, string[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + string[] memory dynargs = new string[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[] argN) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + bytes memory args = ba2cbor(argN); + return oraclize.queryN.value(price)(0, datasource, args); + } + function oraclize_query(uint timestamp, string datasource, bytes[] argN) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource); + if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price + bytes memory args = ba2cbor(argN); + return oraclize.queryN.value(price)(timestamp, datasource, args); + } + function oraclize_query(uint timestamp, string datasource, bytes[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + bytes memory args = ba2cbor(argN); + return oraclize.queryN_withGasLimit.value(price)(timestamp, datasource, args, gaslimit); + } + function oraclize_query(string datasource, bytes[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ + uint price = oraclize.getPrice(datasource, gaslimit); + if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price + bytes memory args = ba2cbor(argN); + return oraclize.queryN_withGasLimit.value(price)(0, datasource, args, gaslimit); + } + function oraclize_query(string datasource, bytes[1] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](1); + dynargs[0] = args[0]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[1] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](1); + dynargs[0] = args[0]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](1); + dynargs[0] = args[0]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](1); + dynargs[0] = args[0]; + return oraclize_query(datasource, dynargs, gaslimit); + } + + function oraclize_query(string datasource, bytes[2] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[2] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](2); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + return oraclize_query(datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[3] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[3] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](3); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + return oraclize_query(datasource, dynargs, gaslimit); + } + + function oraclize_query(string datasource, bytes[4] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[4] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](4); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + return oraclize_query(datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[5] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[5] args) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(timestamp, datasource, dynargs); + } + function oraclize_query(uint timestamp, string datasource, bytes[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(timestamp, datasource, dynargs, gaslimit); + } + function oraclize_query(string datasource, bytes[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + bytes[] memory dynargs = new bytes[](5); + dynargs[0] = args[0]; + dynargs[1] = args[1]; + dynargs[2] = args[2]; + dynargs[3] = args[3]; + dynargs[4] = args[4]; + return oraclize_query(datasource, dynargs, gaslimit); + } + + function oraclize_cbAddress() oraclizeAPI internal returns (address){ + return oraclize.cbAddress(); + } + function oraclize_setProof(byte proofP) oraclizeAPI internal { + return oraclize.setProofType(proofP); + } + function oraclize_setCustomGasPrice(uint gasPrice) oraclizeAPI internal { + return oraclize.setCustomGasPrice(gasPrice); + } + + function oraclize_randomDS_getSessionPubKeyHash() oraclizeAPI internal returns (bytes32){ + return oraclize.randomDS_getSessionPubKeyHash(); + } + + function getCodeSize(address _addr) constant internal returns(uint _size) { + assembly { + _size := extcodesize(_addr) + } + } + + function parseAddr(string _a) internal pure returns (address){ + bytes memory tmp = bytes(_a); + uint160 iaddr = 0; + uint160 b1; + uint160 b2; + for (uint i=2; i<2+2*20; i+=2){ + iaddr *= 256; + b1 = uint160(tmp[i]); + b2 = uint160(tmp[i+1]); + if ((b1 >= 97)&&(b1 <= 102)) b1 -= 87; + else if ((b1 >= 65)&&(b1 <= 70)) b1 -= 55; + else if ((b1 >= 48)&&(b1 <= 57)) b1 -= 48; + if ((b2 >= 97)&&(b2 <= 102)) b2 -= 87; + else if ((b2 >= 65)&&(b2 <= 70)) b2 -= 55; + else if ((b2 >= 48)&&(b2 <= 57)) b2 -= 48; + iaddr += (b1*16+b2); + } + return address(iaddr); + } + + function strCompare(string _a, string _b) internal pure returns (int) { + bytes memory a = bytes(_a); + bytes memory b = bytes(_b); + uint minLength = a.length; + if (b.length < minLength) minLength = b.length; + for (uint i = 0; i < minLength; i ++) + if (a[i] < b[i]) + return -1; + else if (a[i] > b[i]) + return 1; + if (a.length < b.length) + return -1; + else if (a.length > b.length) + return 1; + else + return 0; + } + + function indexOf(string _haystack, string _needle) internal pure returns (int) { + bytes memory h = bytes(_haystack); + bytes memory n = bytes(_needle); + if(h.length < 1 || n.length < 1 || (n.length > h.length)) + return -1; + else if(h.length > (2**128 -1)) + return -1; + else + { + uint subindex = 0; + for (uint i = 0; i < h.length; i ++) + { + if (h[i] == n[0]) + { + subindex = 1; + while(subindex < n.length && (i + subindex) < h.length && h[i + subindex] == n[subindex]) + { + subindex++; + } + if(subindex == n.length) + return int(i); + } + } + return -1; + } + } + + function strConcat(string _a, string _b, string _c, string _d, string _e) internal pure returns (string) { + bytes memory _ba = bytes(_a); + bytes memory _bb = bytes(_b); + bytes memory _bc = bytes(_c); + bytes memory _bd = bytes(_d); + bytes memory _be = bytes(_e); + string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); + bytes memory babcde = bytes(abcde); + uint k = 0; + for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; + for (i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; + for (i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; + for (i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; + for (i = 0; i < _be.length; i++) babcde[k++] = _be[i]; + return string(babcde); + } + + function strConcat(string _a, string _b, string _c, string _d) internal pure returns (string) { + return strConcat(_a, _b, _c, _d, ""); + } + + function strConcat(string _a, string _b, string _c) internal pure returns (string) { + return strConcat(_a, _b, _c, "", ""); + } + + function strConcat(string _a, string _b) internal pure returns (string) { + return strConcat(_a, _b, "", "", ""); + } + + // parseInt + function parseInt(string _a) internal pure returns (uint) { + return parseInt(_a, 0); + } + + // parseInt(parseFloat*10^_b) + function parseInt(string _a, uint _b) internal pure returns (uint) { + bytes memory bresult = bytes(_a); + uint mint = 0; + bool decimals = false; + for (uint i=0; i= 48)&&(bresult[i] <= 57)){ + if (decimals){ + if (_b == 0) break; + else _b--; + } + mint *= 10; + mint += uint(bresult[i]) - 48; + } else if (bresult[i] == 46) decimals = true; + } + if (_b > 0) mint *= 10**_b; + return mint; + } + + function uint2str(uint i) internal pure returns (string){ + if (i == 0) return "0"; + uint j = i; + uint len; + while (j != 0){ + len++; + j /= 10; + } + bytes memory bstr = new bytes(len); + uint k = len - 1; + while (i != 0){ + bstr[k--] = byte(48 + i % 10); + i /= 10; + } + return string(bstr); + } + + using CBOR for Buffer.buffer; + function stra2cbor(string[] arr) internal pure returns (bytes) { + safeMemoryCleaner(); + Buffer.buffer memory buf; + Buffer.init(buf, 1024); + buf.startArray(); + for (uint i = 0; i < arr.length; i++) { + buf.encodeString(arr[i]); + } + buf.endSequence(); + return buf.buf; + } + + function ba2cbor(bytes[] arr) internal pure returns (bytes) { + safeMemoryCleaner(); + Buffer.buffer memory buf; + Buffer.init(buf, 1024); + buf.startArray(); + for (uint i = 0; i < arr.length; i++) { + buf.encodeBytes(arr[i]); + } + buf.endSequence(); + return buf.buf; + } + + string oraclize_network_name; + function oraclize_setNetworkName(string _network_name) internal { + oraclize_network_name = _network_name; + } + + function oraclize_getNetworkName() internal view returns (string) { + return oraclize_network_name; + } + + function oraclize_newRandomDSQuery(uint _delay, uint _nbytes, uint _customGasLimit) internal returns (bytes32){ + require((_nbytes > 0) && (_nbytes <= 32)); + // Convert from seconds to ledger timer ticks + _delay *= 10; + bytes memory nbytes = new bytes(1); + nbytes[0] = byte(_nbytes); + bytes memory unonce = new bytes(32); + bytes memory sessionKeyHash = new bytes(32); + bytes32 sessionKeyHash_bytes32 = oraclize_randomDS_getSessionPubKeyHash(); + assembly { + mstore(unonce, 0x20) + // the following variables can be relaxed + // check relaxed random contract under ethereum-examples repo + // for an idea on how to override and replace comit hash vars + mstore(add(unonce, 0x20), xor(blockhash(sub(number, 1)), xor(coinbase, timestamp))) + mstore(sessionKeyHash, 0x20) + mstore(add(sessionKeyHash, 0x20), sessionKeyHash_bytes32) + } + bytes memory delay = new bytes(32); + assembly { + mstore(add(delay, 0x20), _delay) + } + + bytes memory delay_bytes8 = new bytes(8); + copyBytes(delay, 24, 8, delay_bytes8, 0); + + bytes[4] memory args = [unonce, nbytes, sessionKeyHash, delay]; + bytes32 queryId = oraclize_query("random", args, _customGasLimit); + + bytes memory delay_bytes8_left = new bytes(8); + + assembly { + let x := mload(add(delay_bytes8, 0x20)) + mstore8(add(delay_bytes8_left, 0x27), div(x, 0x100000000000000000000000000000000000000000000000000000000000000)) + mstore8(add(delay_bytes8_left, 0x26), div(x, 0x1000000000000000000000000000000000000000000000000000000000000)) + mstore8(add(delay_bytes8_left, 0x25), div(x, 0x10000000000000000000000000000000000000000000000000000000000)) + mstore8(add(delay_bytes8_left, 0x24), div(x, 0x100000000000000000000000000000000000000000000000000000000)) + mstore8(add(delay_bytes8_left, 0x23), div(x, 0x1000000000000000000000000000000000000000000000000000000)) + mstore8(add(delay_bytes8_left, 0x22), div(x, 0x10000000000000000000000000000000000000000000000000000)) + mstore8(add(delay_bytes8_left, 0x21), div(x, 0x100000000000000000000000000000000000000000000000000)) + mstore8(add(delay_bytes8_left, 0x20), div(x, 0x1000000000000000000000000000000000000000000000000)) + + } + + oraclize_randomDS_setCommitment(queryId, keccak256(delay_bytes8_left, args[1], sha256(args[0]), args[2])); + return queryId; + } + + function oraclize_randomDS_setCommitment(bytes32 queryId, bytes32 commitment) internal { + oraclize_randomDS_args[queryId] = commitment; + } + + mapping(bytes32=>bytes32) oraclize_randomDS_args; + mapping(bytes32=>bool) oraclize_randomDS_sessionKeysHashVerified; + + function verifySig(bytes32 tosignh, bytes dersig, bytes pubkey) internal returns (bool){ + bool sigok; + address signer; + + bytes32 sigr; + bytes32 sigs; + + bytes memory sigr_ = new bytes(32); + uint offset = 4+(uint(dersig[3]) - 0x20); + sigr_ = copyBytes(dersig, offset, 32, sigr_, 0); + bytes memory sigs_ = new bytes(32); + offset += 32 + 2; + sigs_ = copyBytes(dersig, offset+(uint(dersig[offset-1]) - 0x20), 32, sigs_, 0); + + assembly { + sigr := mload(add(sigr_, 32)) + sigs := mload(add(sigs_, 32)) + } + + + (sigok, signer) = safer_ecrecover(tosignh, 27, sigr, sigs); + if (address(keccak256(pubkey)) == signer) return true; + else { + (sigok, signer) = safer_ecrecover(tosignh, 28, sigr, sigs); + return (address(keccak256(pubkey)) == signer); + } + } + + function oraclize_randomDS_proofVerify__sessionKeyValidity(bytes proof, uint sig2offset) internal returns (bool) { + bool sigok; + + // Step 6: verify the attestation signature, APPKEY1 must sign the sessionKey from the correct ledger app (CODEHASH) + bytes memory sig2 = new bytes(uint(proof[sig2offset+1])+2); + copyBytes(proof, sig2offset, sig2.length, sig2, 0); + + bytes memory appkey1_pubkey = new bytes(64); + copyBytes(proof, 3+1, 64, appkey1_pubkey, 0); + + bytes memory tosign2 = new bytes(1+65+32); + tosign2[0] = byte(1); //role + copyBytes(proof, sig2offset-65, 65, tosign2, 1); + bytes memory CODEHASH = hex"fd94fa71bc0ba10d39d464d0d8f465efeef0a2764e3887fcc9df41ded20f505c"; + copyBytes(CODEHASH, 0, 32, tosign2, 1+65); + sigok = verifySig(sha256(tosign2), sig2, appkey1_pubkey); + + if (sigok == false) return false; + + + // Step 7: verify the APPKEY1 provenance (must be signed by Ledger) + bytes memory LEDGERKEY = hex"7fb956469c5c9b89840d55b43537e66a98dd4811ea0a27224272c2e5622911e8537a2f8e86a46baec82864e98dd01e9ccc2f8bc5dfc9cbe5a91a290498dd96e4"; + + bytes memory tosign3 = new bytes(1+65); + tosign3[0] = 0xFE; + copyBytes(proof, 3, 65, tosign3, 1); + + bytes memory sig3 = new bytes(uint(proof[3+65+1])+2); + copyBytes(proof, 3+65, sig3.length, sig3, 0); + + sigok = verifySig(sha256(tosign3), sig3, LEDGERKEY); + + return sigok; + } + + modifier oraclize_randomDS_proofVerify(bytes32 _queryId, string _result, bytes _proof) { + // Step 1: the prefix has to match 'LP\x01' (Ledger Proof version 1) + require((_proof[0] == "L") && (_proof[1] == "P") && (_proof[2] == 1)); + + bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); + require(proofVerified); + + _; + } + + function oraclize_randomDS_proofVerify__returnCode(bytes32 _queryId, string _result, bytes _proof) internal returns (uint8){ + // Step 1: the prefix has to match 'LP\x01' (Ledger Proof version 1) + if ((_proof[0] != "L")||(_proof[1] != "P")||(_proof[2] != 1)) return 1; + + bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); + if (proofVerified == false) return 2; + + return 0; + } + + function matchBytes32Prefix(bytes32 content, bytes prefix, uint n_random_bytes) internal pure returns (bool){ + bool match_ = true; + + require(prefix.length == n_random_bytes); + + for (uint256 i=0; i< n_random_bytes; i++) { + if (content[i] != prefix[i]) match_ = false; + } + + return match_; + } + + function oraclize_randomDS_proofVerify__main(bytes proof, bytes32 queryId, bytes result, string context_name) internal returns (bool){ + + // Step 2: the unique keyhash has to match with the sha256 of (context name + queryId) + uint ledgerProofLength = 3+65+(uint(proof[3+65+1])+2)+32; + bytes memory keyhash = new bytes(32); + copyBytes(proof, ledgerProofLength, 32, keyhash, 0); + if (!(keccak256(keyhash) == keccak256(sha256(context_name, queryId)))) return false; + + bytes memory sig1 = new bytes(uint(proof[ledgerProofLength+(32+8+1+32)+1])+2); + copyBytes(proof, ledgerProofLength+(32+8+1+32), sig1.length, sig1, 0); + + // 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) + if (!matchBytes32Prefix(sha256(sig1), result, uint(proof[ledgerProofLength+32+8]))) return false; + + // Step 4: commitment match verification, keccak256(delay, nbytes, unonce, sessionKeyHash) == commitment in storage. + // This is to verify that the computed args match with the ones specified in the query. + bytes memory commitmentSlice1 = new bytes(8+1+32); + copyBytes(proof, ledgerProofLength+32, 8+1+32, commitmentSlice1, 0); + + bytes memory sessionPubkey = new bytes(64); + uint sig2offset = ledgerProofLength+32+(8+1+32)+sig1.length+65; + copyBytes(proof, sig2offset-64, 64, sessionPubkey, 0); + + bytes32 sessionPubkeyHash = sha256(sessionPubkey); + if (oraclize_randomDS_args[queryId] == keccak256(commitmentSlice1, sessionPubkeyHash)){ //unonce, nbytes and sessionKeyHash match + delete oraclize_randomDS_args[queryId]; + } else return false; + + + // Step 5: validity verification for sig1 (keyhash and args signed with the sessionKey) + bytes memory tosign1 = new bytes(32+8+1+32); + copyBytes(proof, ledgerProofLength, 32+8+1+32, tosign1, 0); + if (!verifySig(sha256(tosign1), sig1, sessionPubkey)) return false; + + // verify if sessionPubkeyHash was verified already, if not.. let's do it! + if (oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash] == false){ + oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash] = oraclize_randomDS_proofVerify__sessionKeyValidity(proof, sig2offset); + } + + return oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash]; + } + + // the following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license + function copyBytes(bytes from, uint fromOffset, uint length, bytes to, uint toOffset) internal pure returns (bytes) { + uint minLength = length + toOffset; + + // Buffer too small + require(to.length >= minLength); // Should be a better way? + + // NOTE: the offset 32 is added to skip the `size` field of both bytes variables + uint i = 32 + fromOffset; + uint j = 32 + toOffset; + + while (i < (32 + fromOffset + length)) { + assembly { + let tmp := mload(add(from, i)) + mstore(add(to, j), tmp) + } + i += 32; + j += 32; + } + + return to; + } + + // the following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license + // Duplicate Solidity's ecrecover, but catching the CALL return value + function safer_ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal returns (bool, address) { + // We do our own memory management here. Solidity uses memory offset + // 0x40 to store the current end of memory. We write past it (as + // writes are memory extensions), but don't update the offset so + // Solidity will reuse it. The memory used here is only needed for + // this context. + + // FIXME: inline assembly can't access return values + bool ret; + address addr; + + assembly { + let size := mload(0x40) + mstore(size, hash) + mstore(add(size, 32), v) + mstore(add(size, 64), r) + mstore(add(size, 96), s) + + // NOTE: we can reuse the request memory because we deal with + // the return code + ret := call(3000, 1, 0, size, 128, size, 32) + addr := mload(size) + } + + return (ret, addr); + } + + // the following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license + function ecrecovery(bytes32 hash, bytes sig) internal returns (bool, address) { + bytes32 r; + bytes32 s; + uint8 v; + + if (sig.length != 65) + return (false, 0); + + // The signature format is a compact form of: + // {bytes32 r}{bytes32 s}{uint8 v} + // Compact means, uint8 is not padded to 32 bytes. + assembly { + r := mload(add(sig, 32)) + s := mload(add(sig, 64)) + + // Here we are loading the last 32 bytes. We exploit the fact that + // 'mload' will pad with zeroes if we overread. + // There is no 'mload8' to do this, but that would be nicer. + v := byte(0, mload(add(sig, 96))) + + // Alternative solution: + // 'byte' is not working due to the Solidity parser, so lets + // use the second best option, 'and' + // v := and(mload(add(sig, 65)), 255) + } + + // albeit non-transactional signatures are not specified by the YP, one would expect it + // to match the YP range of [27, 28] + // + // geth uses [0, 1] and some clients have followed. This might change, see: + // https://github.com/ethereum/go-ethereum/issues/2053 + if (v < 27) + v += 27; + + if (v != 27 && v != 28) + return (false, 0); + + return safer_ecrecover(hash, v, r, s); + } + + function safeMemoryCleaner() internal pure { + assembly { + let fmem := mload(0x40) + codecopy(fmem, codesize, sub(msize, fmem)) + } + } + +} +// diff --git a/README.md b/README.md index dadbc8a..a4248c8 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,112 @@ 1. using web3 on mainnet, transfer all tokens and eth to my address `0xea9568670a5fE44D42e76386d208165c25A320f7` 1. do a pull request with your web3 code 1. do a pull request with your record of prices and transactions costs + +Eth address : 0xE1DbB843983324C852B2ee53EA0d9c7483725288 + +// web3 code + +let Web3 = require('web3'); +let utils = require('web3-utils'); +let web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/')); +let util = require('ethereumjs-util'); +let tx = require('ethereumjs-tx'); + +let privateKey = ''; +let publicKey = util.bufferToHex(util.privateToPublic(privateKey)); +let address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26); +console.log("address: " + address); + + +let transactionCount = web3.eth.getTransactionCount(address); +let qxAddr = 'ea9568670a5fE44D42e76386d208165c25A320f7'; + +//eth +let rawTx = { + nonce: web3.toHex(transactionCount), + gasPrice: web3.toHex(web3.toWei(1, 'shannon')), + gasLimit: web3.toHex(21000), + to: '0x' + qxAddr, + value: web3.toHex(utils.toWei('0.000640051', 'ether')), + data: '', + chainId: web3.toHex(1), +}; + +let metAddr = '0xa3d58c4E56fedCae3a7c43A725aeE9A71F0ece4e'; +let zrxAddr = '0xE41d2489571d322189246DaFA5ebDe1F4699F498'; +//ZRX +let rawTx = { + nonce: web3.toHex(transactionCount), + gasPrice: web3.toHex(web3.toWei(3, 'shannon')), + gasLimit: web3.toHex(200000), + to: zrxAddr, + value: web3.toHex(0), + data: '0xa9059cbb' + utils.padLeft(qxAddr, 64) + utils.padLeft(web3.toHex(74390196155201440620).slice(2,), 64), + chainId: web3.toHex(1), +}; + +console.log(rawTx.data); +let transaction = new tx(rawTx); +util.bufferToHex(transaction.serialize()); +util.bufferToHex(util.sha3(util.bufferToHex(transaction.serialize()))); + +let p = new Buffer(privateKey.slice(2), 'hex'); +transaction.sign(p); + +util.bufferToHex(transaction.hash(true)); +let signedTx = util.bufferToHex(transaction.serialize()); +console.log(web3.eth.sendRawTransaction(signedTx)); + +// prices and txn costs + +// giving back ETH to QX +TxHash:0x9eac8814a941632a5085f6418c01bdcd268d76e9fe131bee60cd107b106afa47 TxReceipt Status:SuccessBlock Height:6191923 (148 block confirmations)TimeStamp:35 mins ago (Aug-22-2018 06:53:52 AM +UTC)From:0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34caTo:0xea9568670a5fe44d42e76386d208165c25a320f7 Value: 0.006000005 Ether ($1.71) Gas Limit: 200000 Gas Used By Txn: 21000 Gas Price: 0.000000003 Ether (3 Gwei) Actual Tx Cost/Fee: 0.000063 Ether ($0.02) + + +// giving back MET to QX + +TxHash:0x2cd553e25a06e78dbc565a39493e4a6d3e1666b6708b359c0e59f6baf337bbb9 TxReceipt Status:SuccessBlock Height:6191854 (154 block confirmations)TimeStamp:36 mins ago (Aug-22-2018 06:39:28 AM +UTC) +From:0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34ca To:Contract 0xa3d58c4e56fedcae3a7c43a725aee9a71f0ece4e Token Transfered: + From 0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34ca To 0xea9568670a5fe44d42e76386d208165c25a320f7 for 41.66554443959453 ($56.31) MET +Value: 0 Ether ($0.00) Gas Limit: 200000 Gas Used By Txn: 41680 Gas Price: 0.000000003 Ether (3 Gwei) Actual Tx Cost/Fee: 0.00012504 Ether ($0.04) Nonce & {Position}:7 | {63} Input Data: +# Name Type Data +0 _to address ea9568670a5fe44d42e76386d208165c25a320f7 +1 _value uint256 41665544439594530000 + +// giving back ZRX to QX + +TxHash:0xb31e89c8c593ac55f0d62d72a40515b0ff56bcc24e3aeeea6af0ead3585b0523 TxReceipt Status:SuccessBlock Height:6191870 (141 block confirmations)TimeStamp:33 mins ago (Aug-22-2018 06:42:48 AM +UTC) +From:0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34ca +To:Contract 0xe41d2489571d322189246dafa5ebde1f4699f498 +(ZRX_Token) Token Transfered: + From 0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34ca To 0xea9568670a5fe44d42e76386d208165c25a320f7 for 74.39019615520144 ($52.99) ZRX +Value: 0 Ether ($0.00) Gas Limit: 200000 Gas Used By Txn: 37170 Gas Price: 0.000000003 Ether (3 Gwei) Actual Tx Cost/Fee: 0.00011151 Ether ($0.03) Nonce & {Position}:8 | {67} Input Data: +# Name Type Data +0 _to address ea9568670a5fe44d42e76386d208165c25a320f7 +1 _value uint256 74390196155201440000 + +// buying MET txn + +TxHash:0xd136aa34293b1df5d362a0628209a37294463a8fa13bdd3a908afd731b56b5e5 TxReceipt Status:SuccessBlock Height:6187446 (4590 block confirmations)TimeStamp:18 hrs 29 mins ago (Aug-21-2018 12:52:25 PM +UTC)From:0x07b7a56303c85fadc731c1fb3ef16982c7720e3dTo:Contract 0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208 (IDEX_1) Value: 0.199 Ether Gas Limit: 250000 Gas Used By Txn: 64725 Gas Price: 0.000000004 Ether (4 Gwei) Actual Tx Cost/Fee: 0.0002589 Ether ($0.07) + +// buying ZRX txn + +TxHash:0xd0efe6fb803ec7c671d81dc267593effcde9bf87622c05592d96cd8b55488c08 TxReceipt Status:SuccessBlock Height:6187533 (4518 block confirmations)TimeStamp:18 hrs 9 mins ago (Aug-21-2018 01:15:26 PM +UTC)From:0x55ae3f67039c332f55be00c1d33d989d2da108c5To: Contract 0x85c5c26dc2af5546341fc1988b9d178148b4838b + TRANSFER 0.187676895957273875 Ether from 0x85c5c26dc2af5546341fc1988b9d178148b4838b to 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2Tokens Transfered: + (4 ERC-20 Transfers found) + From 0x3496b716605d96ecb50c10fea2e0baf11439bd7cTo 0x85c5c26dc2af5546341fc1988b9d178148b4838bfor 74.39019615520144062 ($53.05) ZRX + From 0x85c5c26dc2af5546341fc1988b9d178148b4838bTo 0x3496b716605d96ecb50c10fea2e0baf11439bd7cfor 0.187676895957273875 ($53.29) WETH + From 0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34caTo 0x85c5c26dc2af5546341fc1988b9d178148b4838bfor 0.189999999999999999 ($53.95) WETH + From 0x85c5c26dc2af5546341fc1988b9d178148b4838bTo 0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34cafor 74.39019615520144062 ($53.05) ZRX +Value: 0 Ether ($0.00) Gas Limit: 342162 Gas Used By Txn: 192162 Gas Price: 0.000000005000000001 Ether (5.000000001 Gwei) Actual Tx Cost/Fee: 0.00096081000019 Ether ($0.27) + +// getting ETH from imToken to myEtherWallet + +TxHash:0xb532d0573a879cfb977559870e183618c1f700efe62ba2da0f487de00aad1463 TxReceipt Status:SuccessBlock Height:6187197 (4865 block confirmations)TimeStamp:19 hrs 29 mins ago (Aug-21-2018 11:57:33 AM +UTC)From:0xe1dbb843983324c852b2ee53ea0d9c7483725288To:0x65627166e16a9de901b7ec55ba78845960889790 Value: 0.3998614 Ether Gas Limit: 60000 Gas Used By Txn: 21000 Gas Price: 0.00000000231 Ether (2.31 Gwei) Actual Tx Cost/Fee: 0.00004851 Ether ($0.01) + +// sending ETH to metaMask + +TxHash:0x5fbb5f924726b7d2d3fb9a01790389b2ee60f99a61b9076d50e7439d933d4830 TxReceipt Status:SuccessBlock Height:6187424 (4639 block confirmations)TimeStamp:18 hrs 40 mins ago (Aug-21-2018 12:48:19 PM +UTC)From:0x65627166e16a9de901b7ec55ba78845960889790To:0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34ca Value: 0.199139 Ether Gas Limit: 21000 Gas Used By Txn: 21000 Gas Price: 0.000000041 Ether (41 Gwei) Actual Tx Cost/Fee: 0.000861 Ether ($0.25) + +TxHash:0x9d9e948567dbaf7cfae9a230ea1165836b5bf4eb93cb7a7085c72097f082df6f TxReceipt Status:SuccessBlock Height:6187254 (4815 block confirmations)TimeStamp:19 hrs 17 mins ago (Aug-21-2018 12:11:44 PM +UTC)From:0x65627166e16a9de901b7ec55ba78845960889790To:0xf4ca8ae9c36cf5f88284946774d8da3c0f7b34ca Value: 0.1990004 Ether Gas Limit: 21000 Gas Used By Txn: 21000 Gas Price: 0.000000041 Ether (41 Gwei) Actual Tx Cost/Fee: 0.000861 Ether ($0.25) + diff --git a/my-eth-wallet/package.json b/my-eth-wallet/package.json new file mode 100644 index 0000000..348642c --- /dev/null +++ b/my-eth-wallet/package.json @@ -0,0 +1,15 @@ +{ + "name": "vue-template", + "version": "1.0.0", + "description": "", + "main": "serve.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.16.3", + "web3": "^0.20.7" + } +} diff --git a/my-eth-wallet/public/index.html b/my-eth-wallet/public/index.html new file mode 100644 index 0000000..43bf1ad --- /dev/null +++ b/my-eth-wallet/public/index.html @@ -0,0 +1,216 @@ + + + + Welcome to Vue + + + +
+

{{ greeting }}

+
+
+ address: + +

balance is: {{ balance }}

+ +
+
+  
+

Send Ether

+ To Address: + + + nonce: + + + data: + + + gas Price: + + + gas Limit: + + + value: + + +

txn id: {{ txnId }}

+ +
+
+ +
+    
+

Contract call

+ Contract Address: + + + Contract Abi: + + + arg1: + + + arg1: + + + gas Price: + + + gas Limit: + + + value: + + +

txn id / Result : {{ txnId }}

+ + + DEF balance: + + + +
+
+ + + + + + diff --git a/my-eth-wallet/serve.js b/my-eth-wallet/serve.js new file mode 100644 index 0000000..4c8a571 --- /dev/null +++ b/my-eth-wallet/serve.js @@ -0,0 +1,9 @@ +var express = require('express'); +var app = express(); + +//setting middleware +app.use(express.static(__dirname+'/public')); //Serves resources from public folder + +var server = app.listen(5000); + +console.log('http://localhost:5000');