Blockchain outbound oracle code sample in solidity - blockchain

Being new to Ethereum blockchain, when learning the chainlink/oracles, have found few examples for the inbound oracles. for example getting price of bitcoin or diesel price etc from price feeds or by calling API.
I could not find any example code for the outbound oracle in solidity even after searching on Internet for long hours.
Would appreciate any guidance to get some sample code to practice the outbound oracle.

what i understand is that you are looking for example code to create an outbound oracle in Solidity,here is an example:
contract Chainlink is usingOraclize {
string public EURUSD;
function updatePrice() public payable {
if (oraclizegetPrice("URL") > this.balance) {
//Handle out of funds error
} else {
oraclizequery("URL", "json(http://api.fixer.io/latest?symbols=USD).rates.USD");
}
}
function _callback(bytes32 myid, string result) public {
require(msg.sender == oraclizecbAddress());
EURUSD = result;
}
}
if you want to achieve certain condition is met in solidity code and send this information through an outbound oracle to another smart contract or on any other application, you can achieve that by using the Solidity language's event system, this event system will help you to send data to external service.
here is an example:
contract DummyContract {
event LogSent(bytes32 data);
function sendData(address otherContractAddress, bytes32 data) public {
// execute functions when certain conditions are met
if (someCondition) {
someFunction();
}
emit LogSent(data);
// call other contract
otherContractAddress.call(data);
// call outbound oracle
Oracle.sendData(data);
}
}

Related

How to automate a ChainLink Job to call a smart-contract function that requires the caller to be a given admin address?

ChainLink automation enables conditional execution of smart contracts functions. However, when calling function from the smart contract, it is the ChainLink registry contract that calls the function, and not the address that registered the UpKeep.
Therefore, it is likely that the call will fail if the function to call has a require that forces the caller (msg.sender) to be a given address (admin address for example).
Is it possible to automate such kind of functions (with msg.sender set to a needed address) with ChainLink Automation ?
As an example:
mapping() private _balance;
address public admin;
constructor {
admin = msg.sender;
}
modifier onlyAdmin {
require(msg.sender == admin, "Only admin");
_;
}
function pay(address _account, uint256 _amount) public onlyAdmin {
_balance[_account] += _amount;
}
function getBalance(address _account) public view returns(uint256) {
return _balance[_account];
}
update a balance through Chainlink automation. I expect the balance of _account to update to its previous value + _amount.
_balance[account] = _balance[account] + _amount;
As you said transaction sent by Chainlink automation is signed with Chainlink Registry contract, and as far as I know it is impossible to replace the signature with consumer contract's owner's signature.
I think the better way to do this is to modify the modifier onlyAdmin to add address of registry contract.

Unable to deploy smart contract to Polygon, Gas estimation error, Internal JSON-RPC error

Good afternoon,
I am new to Polygon (but have some Ethereum experience) and I am attempting to deploy the smart contract from the chainlink documentation https://docs.chain.link/docs/fulfilling-requests/ on the Polygon MUMBAI testnet, using remix as my in browser IDE.
I initially attempted to launch the original contract, as published in the docs. I got this error message:
"Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": -32000, "message": "execution reverted" }"
When that failed, I trimmed it down to a smaller, more bare bones contract (in case there is a smart contract size limit on Polygon). Here is the trimmed down code:
// 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";
contract ATestnetConsumer is ChainlinkClient, ConfirmedOwner {
using Chainlink for Chainlink.Request;
uint256 constant private ORACLE_PAYMENT = 1 * LINK_DIVISIBILITY/10;
uint256 public currentPrice;
int256 public changeDay;
bytes32 public lastMarket;
event RequestEthereumPriceFulfilled(
bytes32 indexed requestId,
uint256 indexed price
);
constructor() ConfirmedOwner(msg.sender){
setPublicChainlinkToken();
}
function requestEthereumPrice(address _oracle, string memory _jobId)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), address(this), this.fulfillEthereumPrice.selector);
req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}
function fulfillEthereumPrice(bytes32 _requestId, uint256 _price)
public
recordChainlinkFulfillment(_requestId)
{
emit RequestEthereumPriceFulfilled(_requestId, _price);
currentPrice = _price;
}
function getChainlinkToken() public view returns (address) {
return chainlinkTokenAddress();
}
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer");
}
function cancelRequest(
bytes32 _requestId,
uint256 _payment,
bytes4 _callbackFunctionId,
uint256 _expiration
)
public
onlyOwner
{
cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration);
}
function stringToBytes32(string memory source) private pure returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
return 0x0;
}
assembly { // solhint-disable-line no-inline-assembly
result := mload(add(source, 32))
}
}
}
But I get the same error. My wallet is funded with MATIC and LINK on polygon (mumbai). I am able to deploy the oracle contract to the mumbai testnet (and can see it on polygon scan https://mumbai.polygonscan.com/address/0x078cF10C20f7A8aac7b49F078B38007A49334b96 ), so it appears its all set up correctly, just for some reason this contract errors out.
I also increased the max gas I was willing to pay, I have attempted to just push the transaction through (it mines but the resulting contract fails to have any data https://mumbai.polygonscan.com/address/0xb9bc5681a15353c9b1b19d3db097323b92137ddd ).
I was also able to deploy a contract that does does not use Oracles but is a working contract (on Rinkeby) to Mumbai, further indicating its specific to this contract, or the Chainlink infrastructure on Polygon in general.
Side note, I am attempting to run and use my own Chainlink node on Polygon, but that should not be effecting this issue, as in this demo contract you send the node info and the job ID as parameters when you make a call to this function, its not in the smart contract itself.
What I have considered is wrong:
-Contract size is too big (even after I trimmed it down??)
-MATIC is not the only currency for gas on polygon?
-There is an unknown error in the Chinlink Documentation
-Something unique about Polygon is throwing an error
Thanks!
After going through and commenting line by line, I was able to track down the code that was at fault. I had gone in and changed the LINK address in ChainlinkClient.sol to the mumbai LINK address. As written, the demo code calls setPublicChainlinkToken(); which then assigns the stored value as the link token address. Changing that value to the correct address did not solve my issue. Instead, I used setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB); and that has cleared up my issue.

How to transfer an ERC721 token across networks

Please pardon me if this question sounds dumb, but I am a little new to this concept and there are not many resources out there I could find. Thanks.
Suppose I have created a ERC721 smart contract and used that to mint an NFT token. Now I want to be able to transfer that token from one network to another. I know to mint transfer the NFT to another user, the owner needs to approve the transaction. I have already tried this on rinkeby testnet. But I have no idea how to transfer from say rinkeby testnet to another network. Please see my mint and transfer functions below:
function _transfer(
address _from,
address _to,
uint256 _tokenId
) external payable {
require(ownerOf(_tokenId) == _from);
_owners[_tokenId] = _to;
_balances[_from]--;
_balances[_to]++;
emit Transfer(_from, _to, _tokenId);
}
function _mint(address _to, uint256 _tokenId)
internal
uniqueToken(_tokenId)
notZeroAddress(_to)
{
_owners[_tokenId] = _to;
_balances[_to] += 1;
tokenExist[_tokenId] = true;
emit Transfer(address(0), msg.sender, _tokenId);
}
I would appreciate any assistance. Thanks.
Cross chain (network) transactions need a bridge. It can be a centralized one or it can be trust-less and decentralized one like near rainbow bridge.
It's not a trivial problem to tackle.
Following links might give you insight on how it should get done.
near rainbow bridge
avalanche bridge
cosmos IBC
polkadot bridges

How to debug Chainlink job task?

We are trying to call an API(Deployed on my machine using ngrok for testing) from Chainlink. We are following the tutorial at https://docs.chain.link/docs/advanced-tutorial/ and using Rinkeby network. The only things we have changed are job id, oracle id and API URL which returns a simple json.
We can see the transaction happening and even a fee of 0.1 LINK is deducted.
But the API is not called(We know this because I can see the realtime logs of the API) and hence the response value is also not fetched in smart contract.
How to debug this? Is there a way to check logs of the job?
Below is my contract code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
import "#chainlink/contracts/src/v0.7/ChainlinkClient.sol";
/**
* THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY.
* PLEASE DO NOT USE THIS CODE IN PRODUCTION.
*/
contract APIConsumer is ChainlinkClient {
using Chainlink for Chainlink.Request;
uint256 public temperature;
address private oracle;
bytes32 private jobId;
uint256 private fee;
constructor () {
setPublicChainlinkToken();
oracle = 0x46cC5EbBe7DA04b45C0e40c061eD2beD20ca7755;
jobId = "60803b12c6de4443a99a6078aa59ef79";
fee = 0.1 * 10 ** 18; // 0.1 LINK (Varies by network and job)
}
function requestVolumeData() public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
request.add("get", "http://my-api.com");
request.add("path", "temperature");
// Multiply the result by 1000000000000000000 to remove decimals
// int timesAmount = 10**18;
// request.addInt("times", timesAmount);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of int
*/
function fulfill(bytes32 _requestId, uint256 _temperature) public recordChainlinkFulfillment(_requestId) {
temperature = _temperature;
}
// function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract
}
The best way to get started debugging chainlink jobs is to look into the logs. There are 2 main ways to look into the logs.
If running in a docker container:
Run this command to find the name of the docker container.
docker ps
Then
docker logs <NAME_OF_DOCKER_CONTAINER>
Read the log.jsonl file.
If you created this in your .chainlink-rinkeby folder, it'll be in .chainlink-rinkeby/log.jsonl
Otherwise you can read the JSON of the job that you're debugging.

Smart contracts fallback as a catch all delegatecall

I am practicing some vulnerabilities in smart contracts for my lecture in the university.
The contracts that I am practicing on are;
contract Company is CompanyInterface {
address public ceo;
...
function setCeo(address newCeo){
ceo = newCeo;
}
...
}
contract MainCompany is CompanyInterface {
address public ceo;
address public lib; // address of Company contract
...
function() payable external {
if(!lib.delegatecall(msg.data)) {
revert();
}
}
...
}
Here, I try to make myself ceo of the MainCompany. However, I couldn't figure out how to call setCeo here. As I know that when an attacker calls MainCompany.setCeo(attacker), MainCompany's fallback function should be triggered when the function (setCeo) can't be found in the MainCompany contract. However, it doesn't happen.
My approach is to create an attacker contract. In that contract, I created a function that does the following;
<addressOfMainCompany>.call.value(1)(bytes4(keccak256("setCeo(address)")), address(0x4b9...));
But ceo is still same. What is the correct way of changing ceo of the MainCompany here?
Thanks