Created
February 19, 2017 03:47
-
-
Save AlwaysBCoding/556a9a47f75c2950b3a3035197594230 to your computer and use it in GitHub Desktop.
Ethereum Ðapp Development - Video 12 | Oracles and Oraclize
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.0;//please import oraclizeAPI_pre0.4.sol when solidity < 0.4.0 | |
contract OraclizeI { | |
address public cbAddress; | |
function query(uint _timestamp, string _datasource, string _arg) payable returns (bytes32 _id); | |
function query_withGasLimit(uint _timestamp, string _datasource, string _arg, uint _gaslimit) payable returns (bytes32 _id); | |
function query2(uint _timestamp, string _datasource, string _arg1, string _arg2) payable returns (bytes32 _id); | |
function query2_withGasLimit(uint _timestamp, string _datasource, string _arg1, string _arg2, uint _gaslimit) payable returns (bytes32 _id); | |
function getPrice(string _datasource) returns (uint _dsprice); | |
function getPrice(string _datasource, uint gaslimit) returns (uint _dsprice); | |
function useCoupon(string _coupon); | |
function setProofType(byte _proofType); | |
function setConfig(bytes32 _config); | |
function setCustomGasPrice(uint _gasPrice); | |
} | |
contract OraclizeAddrResolverI { | |
function getAddress() returns (address _addr); | |
} | |
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 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) oraclize_setNetwork(networkID_auto); | |
oraclize = OraclizeI(OAR.getAddress()); | |
_; | |
} | |
modifier coupon(string code){ | |
oraclize = OraclizeI(OAR.getAddress()); | |
oraclize.useCoupon(code); | |
_; | |
} | |
function oraclize_setNetwork(uint8 networkID) internal returns(bool){ | |
if (getCodeSize(0x1d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed)>0){ //mainnet | |
OAR = OraclizeAddrResolverI(0x1d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed); | |
return true; | |
} | |
if (getCodeSize(0xc03a2615d5efaf5f49f60b7bb6583eaec212fdf1)>0){ //ropsten testnet | |
OAR = OraclizeAddrResolverI(0xc03a2615d5efaf5f49f60b7bb6583eaec212fdf1); | |
return true; | |
} | |
if (getCodeSize(0x20e12a1f859b3feae5fb2a0a32c18f5a65555bbf)>0){ //ether.camp ide | |
OAR = OraclizeAddrResolverI(0x20e12a1f859b3feae5fb2a0a32c18f5a65555bbf); | |
return true; | |
} | |
if (getCodeSize(0x93bbbe5ce77034e3095f0479919962a903f898ad)>0){ //norsborg testnet | |
OAR = OraclizeAddrResolverI(0x93bbbe5ce77034e3095f0479919962a903f898ad); | |
return true; | |
} | |
if (getCodeSize(0x51efaf4c8b3c9afbd5ab9f4bbc82784ab6ef8faa)>0){ //browser-solidity | |
OAR = OraclizeAddrResolverI(0x51efaf4c8b3c9afbd5ab9f4bbc82784ab6ef8faa); | |
return true; | |
} | |
return false; | |
} | |
function __callback(bytes32 myid, string result) { | |
__callback(myid, result, new bytes(0)); | |
} | |
function __callback(bytes32 myid, string result, bytes proof) { | |
} | |
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_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_setConfig(bytes32 config) oraclizeAPI internal { | |
return oraclize.setConfig(config); | |
} | |
function getCodeSize(address _addr) constant internal returns(uint _size) { | |
assembly { | |
_size := extcodesize(_addr) | |
} | |
} | |
function parseAddr(string _a) internal 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 >= 48)&&(b1 <= 57)) b1 -= 48; | |
if ((b2 >= 97)&&(b2 <= 102)) b2 -= 87; | |
else if ((b2 >= 48)&&(b2 <= 57)) b2 -= 48; | |
iaddr += (b1*16+b2); | |
} | |
return address(iaddr); | |
} | |
function strCompare(string _a, string _b) internal 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 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 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 returns (string) { | |
return strConcat(_a, _b, _c, _d, ""); | |
} | |
function strConcat(string _a, string _b, string _c) internal returns (string) { | |
return strConcat(_a, _b, _c, "", ""); | |
} | |
function strConcat(string _a, string _b) internal returns (string) { | |
return strConcat(_a, _b, "", "", ""); | |
} | |
// parseInt | |
function parseInt(string _a) internal returns (uint) { | |
return parseInt(_a, 0); | |
} | |
// parseInt(parseFloat*10^_b) | |
function parseInt(string _a, uint _b) internal returns (uint) { | |
bytes memory bresult = bytes(_a); | |
uint mint = 0; | |
bool decimals = false; | |
for (uint i=0; i<bresult.length; i++){ | |
if ((bresult[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 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); | |
} | |
} | |
// </ORACLIZE_API> | |
contract CoinFlipOracle is usingOraclize { | |
string public result; | |
bytes32 public oraclizeID; | |
function flipCoin() payable { | |
oraclizeID = oraclize_query("WolframAlpha", "flip a coin"); | |
} | |
function __callback(bytes32 _oraclizeID, string _result) { | |
if(msg.sender != oraclize_cbAddress()) throw; | |
result = _result; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Config | |
global.config = { | |
rpc: { | |
host: "localhost", | |
port: "8545" | |
} | |
} | |
// Load Libraries | |
global.solc = require("solc") | |
global.EthTx = require("ethereumjs-tx") | |
global.EthUtil = require("ethereumjs-util") | |
global.fs = require("fs") | |
global.Web3 = require("web3") | |
global.lodash = require("lodash") | |
global.SolidityFunction = require("web3/lib/web3/function") | |
// Connect Web3 Instance | |
// global.web3 = new Web3(new Web3.providers.HttpProvider(`http://${global.config.rpc.host}:${global.config.rpc.port}`)) | |
// global.web3 = new Web3(new Web3.providers.HttpProvider(`https://mainnet.infura.io/EjLdRlni9SfrUBEnnvVt`)) | |
global.web3 = new Web3(new Web3.providers.HttpProvider(`https://ropsten.infura.io/EjLdRlni9SfrUBEnnvVt`)) | |
// global.ENS = require("./ensutils.js") | |
// global.ens = new ENS(global.web3) | |
// Global Account Accessors | |
// global.acct1 = web3.eth.accounts[0] | |
// global.acct2 = web3.eth.accounts[1] | |
// global.acct3 = web3.eth.accounts[2] | |
// global.acct4 = web3.eth.accounts[3] | |
// global.acct5 = web3.eth.accounts[4] | |
// Helper Functions | |
class Helpers { | |
contractName(source) { | |
var re1 = /contract.*{/g | |
var re2 = /\s\w+\s/ | |
return source.match(re1).pop().match(re2)[0].trim() | |
} | |
createContract(source, options={}) { | |
var compiled = solc.compile(source) | |
var contractName = this.contractName(source) | |
var bytecode = compiled["contracts"][contractName]["bytecode"] | |
var abi = JSON.parse(compiled["contracts"][contractName]["interface"]) | |
var contract = global.web3.eth.contract(abi) | |
var gasEstimate = global.web3.eth.estimateGas({ data: bytecode }) | |
var deployed = contract.new(Object.assign({ | |
from: global.web3.eth.accounts[0], | |
value: global.web3.toWei(3, 'ether'), | |
data: bytecode, | |
gas: gasEstimate, | |
gasPrice: global.web3.eth.gasPrice | |
}, options), (error, result) => { }) | |
return deployed | |
} | |
loadContract(name) { | |
var path = `./${name.toLowerCase()}.sol` | |
return fs.readFileSync(path, 'utf8') | |
} | |
contractObject(name) { | |
var source = this.loadContract(name) | |
var compiled = solc.compile(source) | |
var contractName = this.contractName(source) | |
var bytecode = compiled["contracts"][contractName]["bytecode"] | |
var abi = JSON.parse(compiled["contracts"][contractName]["interface"]) | |
var contract = global.web3.eth.contract(abi) | |
return contract | |
} | |
deployedObject(name, address) { | |
var source = this.loadContract(name) | |
var compiled = solc.compile(source) | |
var contractName = this.contractName(source) | |
var bytecode = compiled["contracts"][contractName]["bytecode"] | |
var abi = JSON.parse(compiled["contracts"][contractName]["interface"]) | |
var contract = global.web3.eth.contract(abi) | |
return contract.at(address) | |
} | |
signContractCall() { | |
var deployed = arguments['0'].deployed | |
var methodName = arguments['0'].methodName | |
var pKeyx = arguments['0'].pKeyx | |
var fromAddress = arguments['0'].fromAddress | |
var args = [...arguments]; var params = args.slice(1, args.length); | |
var solidityFunction = new global.SolidityFunction('', lodash.find(deployed.abi, { name: methodName }), '') | |
var payloadData = solidityFunction.toPayload(params).data | |
var rawTx = { | |
nonce: global.web3.toHex(global.web3.eth.getTransactionCount(fromAddress)), | |
gasPrice: global.web3.toHex(global.web3.eth.gasPrice), | |
gasLimit: global.web3.toHex(300000), | |
to: deployed.address, | |
from: fromAddress, | |
data: payloadData | |
} | |
var tx = new global.EthTx(rawTx) | |
tx.sign(pKeyx) | |
return tx.serialize().toString('hex') | |
} | |
callContract() { | |
var deployed = arguments['0'].deployed | |
var methodName = arguments['0'].methodName | |
var pKeyx = arguments['0'].pKeyx | |
var fromAddress = arguments['0'].fromAddress | |
var args = [...arguments]; var params = args.slice(1, args.length); | |
var solidityFunction = new global.SolidityFunction('', lodash.find(deployed.abi, { name: methodName }), '') | |
var payloadData = solidityFunction.toPayload(params).data | |
var rawTx = { | |
nonce: global.web3.toHex(global.web3.eth.getTransactionCount(fromAddress)), | |
gasPrice: global.web3.toHex(global.web3.eth.gasPrice), | |
gasLimit: global.web3.toHex(300000), | |
to: deployed.address, | |
from: fromAddress, | |
data: payloadData | |
} | |
var tx = new global.EthTx(rawTx) | |
tx.sign(pKeyx) | |
var txData = tx.serialize().toString('hex') | |
global.web3.eth.sendRawTransaction(`0x${txData}`, (error, txHash) => { | |
if(error) { | |
console.log(`ERROR...`) | |
console.log(error) | |
} else { | |
console.log(`TxHash...`) | |
console.log(txHash) | |
} | |
}) | |
return true | |
} | |
deployContract(name, options={}) { | |
var source = this.loadContract(name) | |
return this.createContract(source, options) | |
} | |
etherBalance(contract) { | |
switch(typeof(contract)) { | |
case "object": | |
if(contract.address) { | |
return global.web3.fromWei(global.web3.eth.getBalance(contract.address), 'ether').toNumber() | |
} else { | |
return new Error("cannot call getEtherBalance on an object that does not have a property 'address'") | |
} | |
break | |
case "string": | |
return global.web3.fromWei(global.web3.eth.getBalance(contract), 'ether').toNumber() | |
break | |
} | |
} | |
} | |
// Load Helpers into Decypher namespace | |
global.decypher = new Helpers() | |
// Start repl | |
require('repl').start({}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Private Key | |
23e4dfb937932332a3cf17f1fc0541e7dc2b7d0bef81289bfa04a251443b5666 | |
// Address | |
0x08Cf02070Bb9F167556C677DA58e6678bbE871fc | |
// Etherscan URI | |
https://testnet.etherscan.io/address/0x08cf02070bb9f167556c677da58e6678bbe871fc |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can this contract work on the Rinkeby test-net? I changed the configuration in 'decypher.js' and just deployed this contract on Rinkeby but the transaction using filpCoin() function got the TxReceipt Status: Fail. But I just don't know what's wrong with it.
Here is the failed contract: https://rinkeby.etherscan.io/address/0x2a2d8ee7ec2d2a63bb5396ba6a3cf7eabe0cbfa5