Job error on a multi-chain chainlink node version:1.2.0 - chainlink

I have a chainlink node running on two chains evmChainID=4(rinkeby) and evmChainID=80001(Mumbai-polygon)
I have deployed a TestnetConsumer contract on Mumbai which fetches the latest Ethereum price.
The Jobspec created for the consuming contract is as follows:
type = "directrequest"
schemaVersion = 1
name = "Get > Uint256-MUMBAI-POLYGON"
externalJobID = "1d77fe57-fd0c-4ee7-ba6e-e5e40a0e72c4"
maxTaskDuration = "0s"
contractAddress = "0x-my-oracle-contract"
evmChainID = "80001"
minIncomingConfirmations = 0
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)"]
fetch [type="http" method=GET url="$(decode_cbor.get)"]
parse [type="jsonparse" path="$(decode_cbor.path)" data="$(fetch)"]
multiply [type="multiply" input="$(parse)" times=100]
encode_data [type="ethabiencode" abi="(uint256 value)" data="{ \\"value\\": $(multiply) }"]
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="0x-my-oracle-contract" data="$(encode_tx)" evmChainID="80001"]
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
The job runs keep getting success and error alternatively. The error happens because the node tries to send the txn using the key bound to evmChainID=4 as shown in the screenshot.
Errors:
while creating transaction: cannot send transaction on chain ID 80001; eth key with address 0xED3413f20d7F16B5E8934aFf935FD763a3Bd63Cf is pegged to chain ID 4: task run failed
It seems its an error related to some default config. Please help. Thanks
The expectation is the Job spec written specific for evmChainID=80001 will use the key bound to the same evmChainID. The keys were created with CLI.

Related

Requesting random number on Chainlink Testnet and getting zeroes

I have been working on something that encapsulates chainlink random number on nfts to provide them to users, using a chainlink subscription and adding my smart contract as a comsumer. When working on testnet I am finding some times it gives me zero numbers and not a random one. This behaviour is random. Subscription is funded and smart contract added as a comsumer.
May this happen on mainnet also?
On most cases this kind of errors are only testnet timeouts, or other stuff related to slower infrastructure.
I wish to implement something to prevent shipping the NFT when zeroes are recevied:
I tried to put assert(randomNumber!=[zero]); but I got some errors, as gas stimation functions on wallets can ensure this, so they set highest fee.
Any suggestions to keep this secured?
This is the main testnet smart contract bsc address https://testnet.bscscan.com/address/0x74623BaE2c3AcC39Db224c236229dc4d5aD1F64d#code
is there any warranty the request random number operation finishes succesfully, or how can I take care of it on my code?
I have posted chainlink related functions too, where I slice the numbers to get them one by one in the lottery.
Subscription is funded and smart contract added as a comsumer. geting some times zero numbers and not a random one
these are the two functions
function closeSaleGetWinner()
external
nonReentrant
onlyRole(OPERATOR_ROLE)
{
requestRandomWords();
require(
isDrawLive,
"There's not a live draw neither ticket sale is opened"
);
uint256[6] memory numberOfMatches;
uint256 drawPrice;
// set the total pool price to BUSD smart contract balance
drawPrice =
checkBUSDContractBalance() *
allDraws[currentDraw].poolPercentage; // use 1 * 10**18 for use the whole pool
// close ticket sale and get random winner number from s_randomWords
isDrawLive = false;
//assert(s_randomWords[0]!=0);
allDraws[currentDraw].winnerNumber = s_slicedRandomWords;
//unchecked {
uint256 j;
Ticket storage _ticket;
uint256 _match;
// check and update matched numbers per ticket on allTickets structure
for (uint256 i = 0; i < drawToTickets[currentDraw].length; i++) {
j = drawToTickets[currentDraw][i];
_ticket = allTickets[j];
_match = checkWinner(_ticket);
_ticket.matchedNumbers = _match;
numberOfMatches[_match] = numberOfMatches[_match] + 1;
}
// after storing number of winners with [_match] matches calculate win per group
// it's time to overwrite reward variable with
// 1st the part of the price from the total pool for #i number of matches
// 2nd divide e
for (uint256 i = 0; i < 5; i++) {
allDraws[currentDraw].reward[i] =
allDraws[currentDraw].reward[i] *
drawPrice;
if (numberOfMatches[i + 1] > 0) {
allDraws[currentDraw].reward[i] = SafeMath.div(
allDraws[currentDraw].reward[i],
numberOfMatches[i + 1]
);
} else {
allDraws[currentDraw].reward[i] = 0;
}
}
// once stored delete random generated number for further checks
delete (s_randomWords);
delete (s_slicedRandomWords);
}
/*
compares the ticket number with the winner number of the draw and returns a value
representing matched number between 0 to 5 (6 values)
*/
function checkWinner(Ticket storage t) internal view returns (uint256) {
uint256 _match = 0;
// we go and compare digit by digit storing number of consecutive matches and stopping when
// there are no more coincidences
uint256[5] memory ticketNumber = t.number;
uint256[5] memory winnerNumber = allDraws[_drawIdCounter.current() - 1]
.winnerNumber;
for (uint256 i = 0; i < 5; i++) {
// If there exists any distinct
// lastTicketDigit, then return No
if (ticketNumber[i] == winnerNumber[i]) {
_match = _match + 1;
} else return _match;
}
return _match;
}
function buyRandomTicket() public nonReentrant {
uint256[] storage myTickets = accounts[msg.sender].myTicketsHistory;
require(isDrawLive, "Sorry there's no live draw by now");
require(!Address.isContract(msg.sender), "only EOA allowed");
address user = address(msg.sender);
uint256 _value = allDraws[currentDraw].ticketPrice;
// check balance and user allowance
uint256 busdUserBalance = BUSD.balanceOf(msg.sender);
require(busdUserBalance >= _value, "Not enough balance");
uint256 allowance = BUSD.allowance(msg.sender, address(this));
require(allowance >= _value, "Check the BUSD allowance");
uint256 devsReward = _value.mul(5).div(100);
uint256 otherReward = _value.mul(20).div(100);
// get payment
BUSD.safeTransferFrom(msg.sender, address(this), _value);
requestRandomWords();
BUSD.safeTransfer(w1, devsReward);
BUSD.safeTransfer(w2, devsReward);
BUSD.safeTransfer(w3, otherReward);
/*pay referral*/
if (accounts[msg.sender].referrer != address(0))
payReferral(_value, address(msg.sender));
Ticket memory randomTicket = Ticket(
user,
currentDraw,
_ticketIdCounter.current(),
s_slicedRandomWords,
false,
0
);
//require(s_randomWords[0]!=0);
uint256[] storage drawTickets = drawToTickets[currentDraw];
// add to the mapping to store tickets sold for a draw
drawTickets.push(randomTicket.ticketID);
myTickets.push(randomTicket.ticketID);
allTickets.push(randomTicket);
safeMint(user);
// set to 0 random storage variable for further checks
delete (s_randomWords);
delete (s_slicedRandomWords);
}
/* CHAINLINK FUNCTIONS */
// Assumes the subscription is funded sufficiently.
function requestRandomWords() internal {
// Will revert if subscription is not set and funded.
s_requestId = COORDINATOR.requestRandomWords(
keyHash,
s_subscriptionId,
requestConfirmations,
callbackGasLimit,
numWords
);
}
function fulfillRandomWords(
uint256, /* requestId */
uint256[] memory randomWords
) internal override {
uint256 _lastDigit;
s_randomWords = randomWords;
uint256 aux = randomWords[0];
for (uint256 i = 0; i < 5; i++) {
_lastDigit = aux % 10;
s_slicedRandomWords[i] = _lastDigit;
aux = aux / 10;
}
}
```

Chainlink Node Operator Create Job, Unknown Task Type "ETHTX"

I am a Chainlink beginner attempting to set up a Chainlink node on Rinkeby. I have the node running and can access the operator GUI. When I attempt to set up a job (following the documentation here: https://docs.chain.link/docs/fulfilling-requests/) I copy and paste the TOML blob into the field, update my oracle address.
type = "directrequest"
schemaVersion = 1
name = "Get > Uint256"
contractAddress = "updated_addr"
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)"]
fetch [type="http" method=GET url="$(decode_cbor.get)"]
parse [type="jsonparse" path="$(decode_cbor.path)" data="$(fetch)"]
multiply [type="multiply" input="$(parse)" times=100]
encode_data [type="ethabiencode" abi="(uint256 value)" data="{ \\"value\\": $(multiply) }"]
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="updated_addr" data="$(encode_tx)"]
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
When I attempt to create the job, I get the following error message:
UnmarshalTaskFromMap: unknown task type: "ethtx"
I did some digging in their documentation to see if they had changed the task name, and found this link to this specific task, and it seems to match the example code above.
https://docs.chain.link/docs/jobs/task-types/eth-tx/
I also attempted "eth tx", "eth_tx" and also ethtx without quotes without luck. I assume this has been depreciated and the documentation has not caught up.
Thank you for your time.
It's ethtx, you should just update your Chainlink Node to version 1.0.0 or above

Encoding byte array for performUpkeep() in Chainlink Keepers

We have this code below which will encode a uint256 array into a byte array.
For some reason, performUpkeep() will be successful in Remix IDE but not using Hardhat.
function checkUpkeep(bytes calldata checkData) external view override returns (bool, bytes memory) {
bool flag = false;
uint256 counter = 0;
uint256[] memory numbers = new uint256[](10);
for (uint256 i = 0; i < 10; i+=2) {
numbers[counter++] = i;
}
bytes memory checkData = abi.encode(numbers);
return (flag, checkData);
}
function performUpkeep(bytes calldata performData) external override {
uint256[] memory numbers = abi.decode(performData, (uint256[]));
console.log("The first number is:", numbers[0]);
}
The end goal here is to pass data through to performUpkeep succesfully.
The performUpkeep() function takes an argument of type bytes. It then decodes that argument into an array of uint256. Before passing data to performUpkeep() in Hardhat, you must encode the array of uint256 you wish to pass as an argument according to the standard EVM encoding format.
To do so in Hardhat (Javascript) you can use the ethers.js library to access the defaultAbiCoder object and encode your arguments using it. An example can be seen below
let abiCoder = ethers.utils.defaultAbiCoder;
let dataEncoded = abiCoder.encode([ "uint[]"], [[ 1, 2, 3]]);
await keeperContract.performUpkeep(dataEncoded)

Get name of Bluetooth device from address

Given a Bluetooth device address (represented by a SOCKADDR_BTH struct), is there a way to get the name of the device? using getnameinfo returns EAI_FAMILY ("The sa_family member of socket address structure pointed to by the sa parameter is not supported."):
// {B62C4E8D-62CC-404b-BBBF-BF3E3BBB1374}
DEFINE_GUID(g_guidServiceClass, 0xb62c4e8d, 0x62cc, 0x404b, 0xbb, 0xbf,
0xbf, 0x3e, 0x3b, 0xbb, 0x13, 0x74);
SOCKADDR_BTH SockAddrBthServer;
SockAddrBthServer.addressFamily = AF_BTH;
SockAddrBthServer.serviceClassId = g_guidServiceClass;
SockAddrBthServer.port = 0;
SockAddrBthServer.btAddr = //Filled with Bluetooth device address
char hostname[NI_MAXHOST] = {0};
char servInfo[NI_MAXSERV] = {0};
int ret = getnameinfo((struct sockaddr *) &SockAddrBthServer,
sizeof(SOCKADDR_BTH), hostname, NI_MAXHOST, servInfo, NI_MAXSERV, 0);
Use BluetoothGetDeviceInfo function to get remote device's name. Also you can resolve during discovering.
Please note that device name of NEW device may be empty if you try to read it right after discovering.
The best way is to subscribe for WM_DEVICECHANGE message (refer to MSDN WM_DEVICECHANGE and Bluetooth).

Printing the physical address space of shared memory

In C program I got 2 programs one to store a string in a shared memory and the other program is to print the same string via accessing the shared memory.
program 1->
printf("\n SENDER ADDRESS");
printf("\nTHE ADDRESS IS %p",addr1);
printf("\nENTER THE MESSAGE:");
scanf("%s",addr1);
printf("\nMESSAGE STORED IN %p IS %s",addr1,addr1);
program->2
I am having the same text body in program 2 . **BUT IT IS PRINTING THE LOGICAL ADDRESS. HENCE IN THE OUTPUT IAM GETTING 2 DIFFERENT LOGICAL ADRESS. BUT INSTEAD OF THAT IF I WANT TO HAVE SAME PHYSICAL ADDRESS(TO SATISFY THE COLLEGE PROFFESSOR)HOW CAN I DO.**
PLEASE HELP....
PROGRAM 1:
#include<sys/types.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
main()
{
key_t key;
int shmid;
char* addr1;
key = ftok("/home/tamil/myc/pws.c",'T');
shmid = shmget(key,128*1024,IPC_CREAT|SHM_R|SHM_W);
addr1 = shmat(shmid,0,0);
printf("\nIPC SHARED MEMORY");
printf("\n SENDER ADDRESS");
printf("\nTHE ADDRESS IS %p",addr1);
printf("\nENTER THE MESSAGE:");
scanf("%s",addr1);
printf("\nMESSAGE STORED IN %p IS %s",addr1,addr1);
}
PROGRAM 2:
#include<sys/types.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
main()
{
int shmid;
char* addr1;
key_t key;
key = ftok("/home/tamil/myc/pws.c",'T');
shmid = shmget(key,128*1024,SHM_R|SHM_W);
addr1 = shmat(shmid,0,0);
printf("\nIPC SHARED MEMORY");
printf("\n SENDER ADDRESS");
printf("\nTHE ADDRESSS IS %p",addr1);
printf("\nMESSAGE STORED IN %p IS %s",addr1,addr1);
}
output:
tamil#ubuntu:~/myc$ cc shmget.c
tamil#ubuntu:~/myc$ ./a.out
IPC SHARED MEMORY
SENDER ADDRESS
**THE ADDRESS IS **0xb786c000****
ENTER THE MESSAGE:helloworld
MESSAGE STORED IN **0xb786c000** IS helloworldtamil#ubuntu:~/myc$ cc shmget2.c
tamil#ubuntu:~/myc$ ./a.out
IPC SHARED MEMORY
SENDER ADDRESS
**THE ADDRESSS IS **0xb7706000****
MESSAGE STORED IN **0xb7706000** IS helloworldtamil#ubuntu:~/myc$
Dumping 2 MB of shared mem on Linux.
dd if=/dev/shm/stuff_here of=myshm.dmp bs=1024 count=2048
Might have to mount it first in fstab.

Resources