Search
This oracle checks Google’s DNS service to determine if a given domain is owned by a given blockchain address. Each address is stored in a TXT record.
This guide explains how to call the DNS ownership oracle and verify that a given address owns a specific domain. For instance, we will confirm that the address 0xf75519f611776c22275474151a04183665b7feDe owns www5.infernos.io. Note that the source of data is google dns.
Table of Contents
This guide assumes that you know how to create and deploy smart contracts on the Kovan Testnet using the following tools:
You should be familiar with the Chainlink Basic Request Model. If you are new to developing smart contracts on Ethereum, see the Getting Started guide to learn the basics.
This example operates using the following steps:
constructor()
initializes the address of oracle
, the jobId
, and the fees oraclePayment
. The code example is configured for the Kovan testnet. Check the Network Details section for other networks.requestProof()
function to check that an address owns a domain name. For this example, you can use www5.infernos.io
for the _name
and 0xf75519f611776c22275474151a04183665b7feDe
for the _record
. Notice how these parameters are used to build the Chainlink request. The selector of the fulfill()
function is also passed so that the oracle knows which function to call back with the proof
.proof
. It should return true
.// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import '@chainlink/contracts/src/v0.8/ChainlinkClient.sol';
import '@chainlink/contracts/src/v0.8/ConfirmedOwner.sol';
/**
* Request testnet LINK and ETH here: https://faucets.chain.link/
* Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/
*/
/**
* THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY.
* PLEASE DO NOT USE THIS CODE IN PRODUCTION.
*/
contract DnsOwnershipChainlink is ChainlinkClient, ConfirmedOwner {
using Chainlink for Chainlink.Request;
bytes32 private jobId;
bool public proof;
uint256 oraclePayment;
/**
* Network: Kovan
* Oracle:
* Name: LinkPool
* Listing URL: https://market.link/nodes/323602b9-3831-4f8d-a66b-3fb7531649eb?network=42
* Address: 0xfF07C97631Ff3bAb5e5e5660Cdf47AdEd8D4d4Fd
* Job:
* Name: DNS Record Check
* Listing URL: https://market.link/jobs/bf1a410f-ce93-497d-83ac-e63fed9d83bd?network=42
* ID: 791bd73c8a1349859f09b1cb87304f71
* Fee: 0.1 LINK
*/
constructor() ConfirmedOwner(msg.sender) {
setChainlinkToken(0xa36085F69e2889c224210F603D836748e7dC0088);
setChainlinkOracle(0xfF07C97631Ff3bAb5e5e5660Cdf47AdEd8D4d4Fd);
jobId = '791bd73c8a1349859f09b1cb87304f71';
oraclePayment = (1 * LINK_DIVISIBILITY) / 10; // 0,1 * 10**18 (Varies by network and job)
}
/**
* Request proof to check if the address `_record` owns the DNS name `_name`
*
*/
function requestProof(string memory _name, string memory _record) public onlyOwner {
Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
req.add('name', _name);
req.add('record', _record);
sendChainlinkRequest(req, oraclePayment);
}
/**
* Callback function called by the oracle to submit the `_proof` . If true, this means that the address owns the dns name
*
*/
function fulfill(bytes32 _requestId, bool _proof) public recordChainlinkFulfillment(_requestId) {
proof = _proof;
}
/**
* Allow withdraw of Link tokens from the contract
*/
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
require(link.transfer(msg.sender, link.balanceOf(address(this))), 'Unable to transfer');
}
}
The DNS Ownership Contract example works on the Kovan Testnet. Below are the configuration for other chains.
Payment Amount: 2 LINK
LINK Token Address: 0x514910771AF9Ca656af840dff83E8264EcF986CA
Oracle Address: 0x240BaE5A27233Fd3aC5440B5a598467725F7D1cd
JobID: 6ca2e68622bd421d98c648f056ee7c76
Payment Amount: 0.1 LINK
LINK Token Address: 0xa36085F69e2889c224210F603D836748e7dC0088
Oracle Address: 0xff07c97631ff3bab5e5e5660cdf47aded8d4d4fd
JobID: 791bd73c8a1349859f09b1cb87304f71
Payment Amount: 0.1 LINK
LINK Token address:0x404460C6A5EdE2D891e8297795264fDe62ADBB75
Oracle Address: 0x63B72AF260E8b40A7b89E238FeB53448A97b03D2
JobID: fb06afd5a9df4e6cb156f6b797b63a24
Payment Amount: 0.1 LINK
LINK Token Address: 0xb0897686c545045aFc77CF20eC7A532E3120E0F1
Oracle Address: 0x63B72AF260E8b40A7b89E238FeB53448A97b03D2
JobID: f3daed2990114e98906aaf21c4172da3
The DNS Ownership node uses a Chainlink v2 direct-request job. It is composed by the following taks:
type = "directrequest"
schemaVersion = 1
contractAddress = "0x0000000000000000000000000000000000000000"
maxTaskDuration = "0s"
observationSource = """
decode_log [type=ethabidecodelog
abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)"
data="$(jobRun.logData)"
topics="$(jobRun.logTopics)"]
decode_cbor [type=cborparse data="$(decode_log.data)"]
dnsproof [type=bridge
name="dnsproof"
requestData="{\\"data\\": {\\"endpoint\\": \\"dnsProof\\", \\"name\\": $(decode_cbor.name), \\"record\\": $(decode_cbor.record)}}"]
result_parse [type=jsonparse data="$(dnsproof)" path="result"]
encode_data [type=ethabiencode
abi="(bool _result)"
data="{\\"_requestId\\": $(decode_log.requestId),\\"_result\\": $(result_parse)}"]
encode_tx [type=ethabiencode
abi="fulfillOracleRequest(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes32 data)"
data="{\\"requestId\\": $(decode_log.requestId),\\"payment\\": $(decode_log.payment),\\"callbackAddress\\": $(decode_log.callbackAddr),\\"callbackFunctionId\\": $(decode_log.callbackFunctionId),\\"expiration\\": $(decode_log.cancelExpiration),\\"data\\": $(encode_data)}"]
submit_tx [type=ethtx to="0x0000000000000000000000000000000000000000" data="$(encode_tx)" minConfirmations="2"]
decode_log -> decode_cbor -> dnsproof -> result_parse -> encode_data -> encode_tx -> submit_tx
"""