Skip to content

Commit

Permalink
add oracle contract written by ont smartcontract
Browse files Browse the repository at this point in the history
  • Loading branch information
siovanus committed May 19, 2020
1 parent f9c7098 commit d750a46
Show file tree
Hide file tree
Showing 12 changed files with 1,635 additions and 0 deletions.
Empty file added ont-contracts/README.md
Empty file.
100 changes: 100 additions & 0 deletions ont-contracts/chainlink.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
############ Chainlink Library#########
from ontology.interop.System.App import RegisterAppCall

defaultBufferSize = 256
BufferCall = RegisterAppCall('d5f12664535717af51f52fe2aa88a18d327ea1b9', 'operation', 'args')
CBORCall = RegisterAppCall('3f75e2814021abed8a616da8d408d1347cac988f', 'operation', 'args')


def Main(operation, args):
if operation == 'initialize':
assert (len(args) == 3)
id = args[0]
callbackAddress = args[1]
callbackFunction = args[2]
return initialize(id, callbackAddress, callbackFunction)

if operation == 'setBuffer':
assert (len(args) == 2)
request = args[0]
data = args[1]
return setBuffer(request, data)

if operation == 'add':
assert (len(args) == 3)
request = args[0]
key = args[1]
value = args[2]
return add(request, key, value)

if operation == 'addBytes':
assert (len(args) == 3)
request = args[0]
key = args[1]
value = args[2]
return addBytes(request, key, value)

if operation == 'addUInt':
assert (len(args) == 3)
request = args[0]
key = args[1]
value = args[2]
return addUInt(request, key, value)

if operation == 'addInt':
assert (len(args) == 3)
request = args[0]
key = args[1]
value = args[2]
return addInt(request, key, value)

if operation == 'addStringArray':
assert (len(args) == 3)
request = args[0]
key = args[1]
values = args[2]
return addStringArray(request, key, values)

return True


def initialize(id, callbackAddress, callbackFunction):
return [id, callbackAddress, callbackFunction, 0, None]


def setBuffer(request, data):
request[4] = BufferCall('WriteBytes', [data, request[4]])
return [request[0], request[1], request[2], request[3], request[4]]


def add(request, key, value):
request[4] = CBORCall('encodeString', [request[4], key])
request[4] = CBORCall('encodeString', [request[4], value])
return [request[0], request[1], request[2], request[3], request[4]]


def addBytes(request, key, value):
request[4] = CBORCall('encodeString', [request[4], key])
request[4] = CBORCall('encodeBytes', [request[4], value])
return [request[0], request[1], request[2], request[3], request[4]]


def addInt(request, key, value):
request[4] = CBORCall('encodeString', [request[4], key])
request[4] = CBORCall('encodeInt', [request[4], value])
return [request[0], request[1], request[2], request[3], request[4]]


def addUInt(request, key, value):
request[4] = CBORCall('encodeString', [request[4], key])
request[4] = CBORCall('encodeUInt', [request[4], value])
return [request[0], request[1], request[2], request[3], request[4]]


def addStringArray(request, key, values):
request[4] = CBORCall('encodeString', [request[4], key])
request[4] = CBORCall('startArray', [request[4]])
for i in range(len(values)):
request[4] = CBORCall('encodeString', [request[4], values[i]])
request[4] = CBORCall('endSequence', [request[4]])
return [request[0], request[1], request[2], request[3], request[4]]
202 changes: 202 additions & 0 deletions ont-contracts/chainlink_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
from ontology.builtins import sha256, concat
from ontology.interop.Ontology.Runtime import Base58ToAddress
from ontology.interop.System.Action import RegisterAction
from ontology.interop.System.App import DynamicAppCall, RegisterAppCall
from ontology.interop.System.ExecutionEngine import GetExecutingScriptHash, GetCallingScriptHash
from ontology.interop.System.Runtime import CheckWitness, Serialize, Notify
from ontology.interop.System.Storage import GetContext, Get, Put, Delete
from ontology.libont import bytearray_reverse
# bb7513b23fae0117eae21eea2cd732e1cc267e7e
AMOUNT_OVERRIDE = 0

SENDER_OVERRIDE = 0

ARGS_VERSION = 1

REQUEST_COUNT = "RequestCount"

ORACLE_ADDRESS = "oracle"
LINK_ADDRESS = "link"

PENDING_REQUESTS_PREFIX = "pendingRequests"

contractHash = GetExecutingScriptHash()

ChainlinkRequestedEvent = RegisterAction("chainlinkRequestedEvent", "requestId")

ChainlinkFulfilledEvent = RegisterAction("chainlinkFulfilledEvent", "requestId")

ChainlinkCancelledEvent = RegisterAction("chainlinkCancelledEvent", "requestId")

ChainlinkCall = RegisterAppCall('db6f26fb0f217d6762aa3d6d38e827789a3128d1', 'operation', 'args')

OWNER = Base58ToAddress("AbG3ZgFrMK6fqwXWR1WkQ1d1EYVunCwknu")

def Main(operation, args):
if operation == 'buildChainlinkRequest':
assert (len(args) == 3)
_specId = args[0]
callbackAddress = args[1]
callbackFunction = args[2]
return buildChainlinkRequest(_specId, callbackAddress, callbackFunction)

if operation == 'sendChainlinkRequest':
assert (len(args) == 3)
caller = args[0]
req = args[1]
payment = args[2]
return sendChainlinkRequest(caller, req, payment)

if operation == 'sendChainlinkRequestTo':
assert (len(args) == 4)
caller = args[0]
oracle = args[1]
req = args[2]
payment = args[3]
return sendChainlinkRequestTo(caller, oracle, req, payment)

if operation == 'cancelChainlinkRequest':
assert (len(args) == 5)
sender = args[0]
requestId = args[1]
payment = args[2]
callbackFunctionId = args[3]
expiration = args[4]
return cancelChainlinkRequest(sender, requestId, payment, callbackFunctionId, expiration)

if operation == 'setChainlinkOracle':
assert (len(args) == 1)
oracle = args[0]
return setChainlinkOracle(oracle)

if operation == 'setChainlinkToken':
assert (len(args) == 1)
link = args[0]
return setChainlinkToken(link)

if operation == 'chainlinkTokenAddress':
return chainlinkTokenAddress()

if operation == 'chainlinkOracleAddress':
return chainlinkOracleAddress()

if operation == 'addChainlinkExternalRequest':
assert (len(args) == 2)
oracle = args[0]
requestId = args[1]
return addChainlinkExternalRequest(oracle, requestId)

if operation == 'recordChainlinkFulfillment':
assert (len(args) == 2)
sender = args[0]
requestId = args[1]
return recordChainlinkFulfillment(sender, requestId)

return False


def buildChainlinkRequest(_specId, callbackAddress, callbackFunction):
return ChainlinkCall('initialize', [_specId, callbackAddress, callbackFunction])


def sendChainlinkRequest(caller, req, payment):
return sendChainlinkRequestTo(caller, Get(GetContext(), ORACLE_ADDRESS), req, payment)

def sendChainlinkRequestTo(caller, oracle, req, payment):
RequireWitness(caller)
requestCount = Get(GetContext(), REQUEST_COUNT)
requestId = sha256(Serialize([req[1], caller, requestCount]))
req[3] = requestCount
Put(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId), oracle)
ChainlinkRequestedEvent(requestId)
link = Get(GetContext(), LINK_ADDRESS)

params = [caller, oracle, payment,
[SENDER_OVERRIDE, AMOUNT_OVERRIDE, req[0], req[1], req[2], req[3], ARGS_VERSION, req[4], 'oracleRequest']]
assert (DynamicCallFunction(bytearray_reverse(link), "transferAndCall", params))

Put(GetContext(), REQUEST_COUNT, requestCount + 1)
return True


def cancelChainlinkRequest(sender, requestId, payment, callbackFunctionId, expiration):
RequireWitness(sender)
oracle = Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId))
params = [sender, requestId, payment, GetCallingScriptHash(), callbackFunctionId, expiration]
assert (DynamicCallFunction(bytearray_reverse(oracle), "cancelOracleRequest", params))
Delete(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId))
ChainlinkCancelledEvent(requestId)
return True


def setChainlinkOracle(oracle):
RequireWitness(OWNER)
assert (len(oracle) == 20)
Put(GetContext(), ORACLE_ADDRESS, oracle)
return True


def setChainlinkToken(link):
RequireWitness(OWNER)
assert (len(link) == 20)
Put(GetContext(), LINK_ADDRESS, link)
return True


def chainlinkTokenAddress():
return Get(GetContext(), LINK_ADDRESS)


def chainlinkOracleAddress():
return Get(GetContext(), ORACLE_ADDRESS)


def addChainlinkExternalRequest(oracle, requestId):
assert (notPendingRequest(requestId))
Put(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId), oracle)
return True


## TODO
def useChainlinkWithENS(ens, node):
return True


## TODO
def updateChainlinkOracleWithENS():
return True


def recordChainlinkFulfillment(sender, requestId):
assert (sender == Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId)))
# Notify([sender, Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId))])
Delete(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId))
ChainlinkFulfilledEvent(requestId)
return True


def notPendingRequest(requestId):
assert (not Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId)))
return True


def concatKey(str1, str2):
return concat(concat(str1, '_'), str2)


def RequireScriptHash(key):
assert (len(key) == 20)
return True


def RequireWitness(witness):
assert (CheckWitness(witness))
return True


def DynamicCallFunction(callAddress, callbackFunctionId, params):
res = DynamicAppCall(callAddress, callbackFunctionId, params)
if res and res == b'\x01':
return True
else:
return False
88 changes: 88 additions & 0 deletions ont-contracts/demo/chainlink_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from ontology.builtins import concat
from ontology.interop.Ontology.Runtime import Base58ToAddress
from ontology.interop.System.App import RegisterAppCall, DynamicAppCall
from ontology.interop.System.ExecutionEngine import GetExecutingScriptHash, GetCallingScriptHash
from ontology.interop.System.Runtime import CheckWitness, Notify
from ontology.interop.System.Storage import GetContext, Put, Get
from ontology.libont import bytearray_reverse

CURRENT_PRICE = 'CurrentPrice'

OWNER = Base58ToAddress('AbG3ZgFrMK6fqwXWR1WkQ1d1EYVunCwknu')

ChainlinkCall = RegisterAppCall('db6f26fb0f217d6762aa3d6d38e827789a3128d1', 'operation', 'args')
ChainlinkClientCall = RegisterAppCall('da8aed3a33ba8e7159a991070ea19002ebb06c6f', 'operation', 'args')

ContractAddress = GetExecutingScriptHash()


def Main(operation, args):
if operation == 'requestEthereumPrice':
assert (len(args) == 3)
oracle = args[0]
jobId = args[1]
payment = args[2]
return requestEthereumPrice(oracle, jobId, payment)

if operation == 'fulfill':
assert (len(args) == 2)
requestId = args[0]
price = args[1]
return fulfill(requestId, price)

if operation == 'getCurrentPrice':
return getCurrentPrice()

if operation == 'cancelRequest':
assert (len(args) == 4)
requestId = args[0]
payment = args[1]
callBackFunc = args[2]
expiration = args[3]
return cancelRequest(requestId, payment, callBackFunc, expiration)

return False


def requestEthereumPrice(oracle, jobId, payment):
assert (CheckWitness(OWNER))
req = ChainlinkClientCall('buildChainlinkRequest', [jobId, ContractAddress, 'fulfill'])
req = ChainlinkCall('add', [req, "get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD"])
req = ChainlinkCall('add', [req, "path", "USD"])
req = ChainlinkCall('addInt', [req, "times", 100])
# Notify([OWNER, oracle, req, payment])
assert (ChainlinkClientCall('sendChainlinkRequestTo', [OWNER, oracle, req, payment]))
return True


def fulfill(requestId, price):
assert (ChainlinkClientCall('recordChainlinkFulfillment', [bytearray_reverse(GetCallingScriptHash()), requestId]))
# Notify(['test'])
Put(GetContext(), CURRENT_PRICE, price)
return True


def getCurrentPrice():
return Get(GetContext(), CURRENT_PRICE)


def cancelRequest(requestId, payment, callBackFunc, expiration):
assert (CheckWitness(OWNER))
assert (ChainlinkClientCall('cancelChainlinkRequest', [OWNER, requestId, payment, callBackFunc, expiration]))
return True


def concatKey(str1, str2):
return concat(concat(str1, '_'), str2)


def DynamicCallFunction(callAddress, callbackFunctionId, params):
res = DynamicAppCall(callAddress, callbackFunctionId, params)
if res and res == b'\x01':
return True
else:
return False


def DynamicCallFunctionResult(callAddress, callbackFunctionId, params):
return DynamicAppCall(callAddress, callbackFunctionId, params)
Loading

0 comments on commit d750a46

Please sign in to comment.