From 325a1aa9849686cafc52d984484c40a9f800a3a9 Mon Sep 17 00:00:00 2001 From: Pavan Anand Date: Tue, 29 Aug 2017 12:25:47 -0400 Subject: [PATCH 1/4] Refactored all instances of throw to require to refund gas upon failed checks --- oraclizeAPI_0.4.sol | 120 ++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 61 deletions(-) diff --git a/oraclizeAPI_0.4.sol b/oraclizeAPI_0.4.sol index ed86c42..e3b6309 100644 --- a/oraclizeAPI_0.4.sol +++ b/oraclizeAPI_0.4.sol @@ -120,7 +120,7 @@ contract usingOraclize { } function __callback(bytes32 myid, string result, bytes proof) { } - + function oraclize_useCoupon(string code) oraclizeAPI internal { oraclize.useCoupon(code); } @@ -132,7 +132,7 @@ contract usingOraclize { 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 @@ -214,10 +214,10 @@ contract usingOraclize { } 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]; + 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]; @@ -270,7 +270,7 @@ contract usingOraclize { 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]; @@ -380,10 +380,10 @@ contract usingOraclize { } 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]; + 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]; @@ -436,7 +436,7 @@ contract usingOraclize { 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]; @@ -518,7 +518,7 @@ contract usingOraclize { function oraclize_setConfig(bytes32 config) oraclizeAPI internal { return oraclize.setConfig(config); } - + function oraclize_randomDS_getSessionPubKeyHash() oraclizeAPI internal returns (bytes32){ return oraclize.randomDS_getSessionPubKeyHash(); } @@ -663,7 +663,7 @@ contract usingOraclize { } return string(bstr); } - + function stra2cbor(string[] arr) internal returns (bytes) { uint arrlen = arr.length; @@ -747,19 +747,19 @@ contract usingOraclize { } return res; } - - + + string oraclize_network_name; function oraclize_setNetworkName(string _network_name) internal { oraclize_network_name = _network_name; } - + function oraclize_getNetworkName() internal returns (string) { return oraclize_network_name; } - + function oraclize_newRandomDSQuery(uint _delay, uint _nbytes, uint _customGasLimit) internal returns (bytes32){ - if ((_nbytes == 0)||(_nbytes > 32)) throw; + require((_nbytes == 0)||(_nbytes > 32)); bytes memory nbytes = new bytes(1); nbytes[0] = byte(_nbytes); bytes memory unonce = new bytes(32); @@ -771,26 +771,26 @@ contract usingOraclize { mstore(sessionKeyHash, 0x20) mstore(add(sessionKeyHash, 0x20), sessionKeyHash_bytes32) } - bytes[3] memory args = [unonce, nbytes, sessionKeyHash]; + bytes[3] memory args = [unonce, nbytes, sessionKeyHash]; bytes32 queryId = oraclize_query(_delay, "random", args, _customGasLimit); oraclize_randomDS_setCommitment(queryId, sha3(bytes8(_delay), 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); @@ -802,8 +802,8 @@ contract usingOraclize { sigr := mload(add(sigr_, 32)) sigs := mload(add(sigs_, 32)) } - - + + (sigok, signer) = safer_ecrecover(tosignh, 27, sigr, sigs); if (address(sha3(pubkey)) == signer) return true; else { @@ -814,117 +814,115 @@ contract usingOraclize { 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] = 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) - if ((_proof[0] != "L")||(_proof[1] != "P")||(_proof[2] != 1)) throw; - + require((_proof[0] != "L")||(_proof[1] != "P")||(_proof[2] != 1)); + bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); - if (proofVerified == false) throw; - + require(proofVerified == false); + _; } - + function matchBytes32Prefix(bytes32 content, bytes prefix) internal returns (bool){ bool match_ = true; - + for (var i=0; i From 1a379543acb25f0a7699833f1fb14903cad3473e Mon Sep 17 00:00:00 2001 From: Pavan Anand Date: Tue, 29 Aug 2017 16:09:14 -0400 Subject: [PATCH 2/4] Fixed error handling logic with respect to new require and assert functions --- oraclizeAPI_0.4.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/oraclizeAPI_0.4.sol b/oraclizeAPI_0.4.sol index e3b6309..fbca8c6 100644 --- a/oraclizeAPI_0.4.sol +++ b/oraclizeAPI_0.4.sol @@ -759,7 +759,7 @@ contract usingOraclize { } function oraclize_newRandomDSQuery(uint _delay, uint _nbytes, uint _customGasLimit) internal returns (bytes32){ - require((_nbytes == 0)||(_nbytes > 32)); + assert((_nbytes != 0) && (_nbytes < 32)); // Constrain values of _nbytes bytes memory nbytes = new bytes(1); nbytes[0] = byte(_nbytes); bytes memory unonce = new bytes(32); @@ -849,10 +849,10 @@ contract usingOraclize { 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)); + require((_proof[0] == "L")||(_proof[1] == "P")||(_proof[2] == 1)); bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); - require(proofVerified == false); + require(proofVerified != false); _; } @@ -922,7 +922,7 @@ contract usingOraclize { uint minLength = length + toOffset; // Check to make sure buffer is not too small - require(to.length < minLength); + require(to.length > minLength); // NOTE: the offset 32 is added to skip the `size` field of both bytes variables uint i = 32 + fromOffset; From 54ac3032d3cd72a47e1b40f68a40006c87a0a17e Mon Sep 17 00:00:00 2001 From: Pavan Anand Date: Tue, 29 Aug 2017 16:28:21 -0400 Subject: [PATCH 3/4] Minor whitespace fixes and one logic fix in refactored error handling --- oraclizeAPI_0.4.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/oraclizeAPI_0.4.sol b/oraclizeAPI_0.4.sol index fbca8c6..62a3507 100644 --- a/oraclizeAPI_0.4.sol +++ b/oraclizeAPI_0.4.sol @@ -69,7 +69,7 @@ contract usingOraclize { OraclizeI oraclize; modifier oraclizeAPI { - if((address(OAR)==0)||(getCodeSize(address(OAR))==0)) oraclize_setNetwork(networkID_auto); + if ((address(OAR)==0)||(getCodeSize(address(OAR))==0)) oraclize_setNetwork(networkID_auto); oraclize = OraclizeI(OAR.getAddress()); _; } @@ -570,9 +570,9 @@ contract usingOraclize { function indexOf(string _haystack, string _needle) internal returns (int) { bytes memory h = bytes(_haystack); bytes memory n = bytes(_needle); - if(h.length < 1 || n.length < 1 || (n.length > h.length)) + if (h.length < 1 || n.length < 1 || (n.length > h.length)) return -1; - else if(h.length > (2**128 -1)) + else if (h.length > (2**128 -1)) return -1; else { @@ -586,7 +586,7 @@ contract usingOraclize { { subindex++; } - if(subindex == n.length) + if (subindex == n.length) return int(i); } } @@ -852,7 +852,7 @@ contract usingOraclize { require((_proof[0] == "L")||(_proof[1] == "P")||(_proof[2] == 1)); bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); - require(proofVerified != false); + require(proofVerified); _; } From 700969045d8da3a558d0a070d1da4b8a93748454 Mon Sep 17 00:00:00 2001 From: Pavan Anand Date: Fri, 8 Sep 2017 07:58:23 -0400 Subject: [PATCH 4/4] Corrected refactored checkpoint logic --- oraclizeAPI_0.4.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oraclizeAPI_0.4.sol b/oraclizeAPI_0.4.sol index 62a3507..93db367 100644 --- a/oraclizeAPI_0.4.sol +++ b/oraclizeAPI_0.4.sol @@ -849,7 +849,7 @@ contract usingOraclize { 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)); + require((_proof[0] == "L") && (_proof[1] == "P") && (_proof[2] == 1)); bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); require(proofVerified);