Example Oraclize files return 0: string: when called in Remix - solidity

I want to use Oraclize in Remix, to test it. I'm too stupid to use their examples.
How can I make this work?
From their Github I took the YouTube-Views code and copied it into Remix
pragma solidity >= 0.5.0 < 0.6.0;
import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";
contract YoutubeViews is usingOraclize {
string public viewsCount;
event LogYoutubeViewCount(string views);
event LogNewOraclizeQuery(string description);
constructor()
public
{
update(); // Update views on contract creation...
}
function __callback(
bytes32 _myid,
string memory _result
)
public
{
require(msg.sender == oraclize_cbAddress());
viewsCount = _result;
emit LogYoutubeViewCount(viewsCount);
// Do something with viewsCount, like tipping the author if viewsCount > X?
}
function update()
public
payable
{
emit LogNewOraclizeQuery("Oraclize query was sent, standing by for the answer...");
oraclize_query("URL", 'html(https://www.youtube.com/watch?v=9bZkp7q19f0).xpath(//*[contains(#class, "watch-view-count")]/text())');
}
}
When I use the viewCount it returns:
0: string:
This happens with all the other examples aswell.
With WolframAlpha eg. I also get the following error:
transact to WolframAlpha.update errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value. Debug the transaction to get more information.

Ok you don't see the answer like a normal result in Remix:
You have to go under settings and open the Oraclize plug in.
If you then deploy the contract and or click update, you get the result shown in the plug in.

Related

Testing ChainlinkClient callbacks - how to bypass recordChainlinkFulfillment?

I've got a Chainlink client contract which makes a DirectRequest to an oracle. The oracle does its thing and then returns the answer via the typical callback selector passed in via the ChainlinkRequest. It all works well, but I'd like to write some tests that test the callback implementation
My client contract is as follows:
contract PriceFeed is Ownable, ChainlinkClient {
function updatePrice() onlyOwner returns (bytes32 requestId) {
// makes Chainlink request specifying callback via this.requestCallback.selector
}
function requestCallback(bytes32 _requestId, uint256 _newPrice) public
recordChainlinkFulfillment(_requestId) {
price = _newPrice;
}
}
The problem arises when the test code calls requestCallback(...) and the code hits the recordChainlinkFulfillment(...) modifier. The ChainlinkClient complains that the requestId being passed in by the test below isn't in the underling private pendingRequests mapping maintained by the ChainlinkClient.
The simplified version of ChainlinkClient looks like this:
contract ChainlinkClient {
mapping(bytes32 => address) private pendingRequests;
modifier recordChainlinkFulfillment(bytes32 _requestId) {
require(msg.sender == pendingRequests[_requestId], "Source must be the oracle of the request");
delete pendingRequests[_requestId];
emit ChainlinkFulfilled(_requestId);
_;
}
}
My Foundry/Solidity test is as follows:
contract PriceFeedTest is Test {
function testInitialCallback() public {
priceFeed.requestCallback("abc123", 1000000); // fails on this line
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
The code fails on first line of the testInitialCallback() line with: Source must be the oracle of the request
How can I trick the ChainklinkClient into allowing my callback to get past the modifier check? AFAIK I can't access and pre-populate the private pendingRequests mapping. Is there another way?
I know that Foundry provides Cheatcodes to help in testing and there's a stdstorage cheatcode, but I'm not familiar on how to construct a call to stdstorage to override pendingRequests if thats even possible with a cheatcode.
contract PriceFeedTest is Test {
function testInitialCallback2() public {
stdstore
.target(address(priceFeed))
.sig("pendingRequests()")
.with_key("abc123")
.checked_write(address(this));
priceFeed.requestCallback("abc123", 1000000);
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
The above code throws the following error: No storage use detected for target
Any help would be greatly appreciated. Many thanks.
When you execute the updatePrice function in your test, you should be able to strip out the requestId from the transaction receipt event. Once you have that, you can then use it in your call to requestCallback. Check out this example unit test from the hardhat starter kit for an example of this

Chainlink- Issue when fetching an API in form of `bytes32`

I've been learning the chainlink API and trying to modify the example from the Chainlin's documentation to get a byets32 value from an API. The original code of the example works well, but since the API I was hitting is returning a byets32 foem, the Chainlink job need to be configured to handle this type of return. The node is given here with Kovan testnet. Here is my code
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/ChainlinkClient.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 APIConsumer is ChainlinkClient {
using Chainlink for Chainlink.Request;
//Result of the api
bytes32 public martket;
address private oracle;
bytes32 private jobId;
uint256 private fee;
/**
* Get -> bytes32
* Network: Kovan
* Oracle: 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8 (Chainlink Devrel
* Node)
* Job ID: 7401f318127148a894c00c292e486ffd
* Fee: 0.1 LINK
*/
constructor() {
setPublicChainlinkToken();
// Get -> bytes32 node taken from documentation
oracle = 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8;
jobId = "7401f318127148a894c00c292e486ffd";
fee = 0.1 * 10 ** 18; // (Varies by network and job)
}
/**
* Create a Chainlink request to retrieve API response, find the target
* data, then multiply by 1000000000000000000 (to remove decimal places from data).
*/
function requestVolumeData() public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
// Set the URL to perform the GET request on
request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
// Set the path to find the desired data in the API response, where the response format is:
// {"RAW":
// {"ETH":
// {"USD":
// {
// "MARKET": "CCCAGG",
// }
// }
// }
// }
//Get the MARKET field of API
request.add("path", "RAW,ETH,USD,MARKET"); // Chainlink nodes 1.0.0 and later support this format
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of bytes32
*/
function fulfill(bytes32 _requestId, bytes32 _market) public recordChainlinkFulfillment(_requestId)
{
martket = _market;
}
// function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract
}
The value of market should be a byets32 reprsenting "CCCAGG" as shown in the API. But what I got was just 0x0...00 all the time, which means market has not been modified yet. I've checked this various ways and found out that the fulfill function never get rans. Then same thing happens when I changed the jobId and oracle to handle get-> int256, get -> bool (of course I did change the return type of the variable such that it's consistent with the returning form of API). I also noticed that only the job get -> uint256 works well (the example from documentation also used this job). Does anyon know why? Was my code wrong or the problem came from the node/job? Since I was able the get the example right, I don't think the problem cam from my wallet.
Any help would be appreciated!
You can test with a GET>STRING JOB
Go to this link: https://docs.chain.link/docs/any-api-testnet-oracles/
Take the Oracle contract address relevant to your network. For instance: 0xCC79157eb46F5624204f47AB42b3906cAA40eaB7 for Goerli
Use a Get>String job: 7d80a6386ef543a3abb52817f6707e3b
Make sure that your callback function expects to receive a string. (see a full example here: https://docs.chain.link/docs/api-array-response/)

Burning Deployed ERC Tokens In an NFT Mint Function - Compiles, but Transaction Fails

I am very new to Solidity, and have recently been working on trying to learn the ropes. For reference, I have been using code from this video (https://www.youtube.com/watch?v=tBMk1iZa85Y) as a primer after having gone through the basic crypto zombies tutorial series.
I have been attempting to adapt the Solidity contract code presented in this video (which I had functioning just fine!) to require a Burn of a specified amount of an ERC-20 token before minting an NFT as an exercise for myself. I thought I had what should be a valid implementation which compiled in Remix, and then deployed to Rinkeby. I call the allowAccess function in Remix after deploying to Rinkeby, and that succeeds. But, when I call the mint function with the two parameters, I get: "gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? execution reverted."
If I still send the transaction, metamask yields "Transaction xx failed! Transaction encountered an error.".
I'm positive it has to do with "require(paymentToken.transfer(burnwallet, amounttopay),"transfer Failed");", though I'm not sure what's wrong. Below is my entire contract code. I'm currently just interacting with the Chainlink contract on Rinkeby as my example, since they have a convenient token faucet.
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Counters.sol";
contract myNFTwithBurn is ERC721, Ownable {
address externalTokenAddress = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709; //Token Type to burn on minting
uint256 amounttopay = 5; //number of these tokens to burn
IERC20 paymentToken = IERC20(externalTokenAddress); //my code: create an interface of the external token
address burnwallet = 0x000000000000000000000000000000000000dEaD; //burn wallet
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
using Strings for uint256;
// Optional mapping for token URIs
mapping (uint256 => string) private _tokenURIs;
// Base URI
string private _baseURIextended;
constructor() ERC721("NFTsWithBurn","NWB") {
}
function setBaseURI(string memory baseURI_) external onlyOwner() {
_baseURIextended = baseURI_;
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseURIextended;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
return string(abi.encodePacked(base, tokenId.toString()));
}
function allowAccess() public
{
paymentToken.approve(address(this), 5000000); //This is my attempt to allow the contract access to the user's external tokens, in this case Chainlink (paymentToken)
}
function mintItem(address to, string memory tokenURI)
public
onlyOwner
returns (uint256)
{
require(paymentToken.transfer(burnwallet, amounttopay),"transfer Failed"); //Try to transfer 5 chainlink to the burn wallet
_tokenIds.increment();
uint256 id = _tokenIds.current();
_mint(to, id);
_setTokenURI(id, tokenURI);
return id;
}
}
If anybody can at least point me to what I'm doing completely wrong in the code that I've added, please do! TIA!
I'm not sure why are you trying to burn link in order to mint and nft but first check if the link code does not have a require that check if the destination address is the burn address if it has then burn the link is not possible and you should use any other erc20 maybe your own erc20, also your contract probably does not have any link and if you want to transfer the link from the user you should do this in the contract paymentToken.transferFrom(msg.sender,destinationAddress,amount) and if the user previously approve your contract you will able to send the tokens, and i suppose that the purpose of the allowAccess function is to make the user approve the contract to move the tokens that will never work, the approve function let's anyone that call it approve any address to move an amount of tokens, the thing is that to know who is approving to let other to move the tokens the function use msg.sender to explain how this work take a look at this example
let's say that your contract is the contract A and the link contract is the contract B
now a user call allowAccess in the contract A, so here the msg.sender is the user because they call the function
now internally this function call approve on contract B, here the contract A is the msg.sender, because the contract is who call the function
so what allowAccess is really doing is making the contract approving itself to move their own tokens that I assume it doesn't have

Is this a remix,compiler or an openzeplin bug?

I just wrote a simple code to test openzeplin Safemath library. I am using the latest version of remix ide and compiling for ^0.5.0.
Remix is using 0.5.0_commit.1d4f565a compiler
The environment is JavaScript VM
EVM Version is the compiler default
The add function does not seem to be working in the code given below
I have tried x.sub(1) it throws an exception as expected, i have also tried initializing x to different values but still does not work.
pragma solidity ^0.5.0;
import "./SafeMath.sol";
contract SimpleStorage {
using SafeMath for uint;
uint x;
event incremented(uint x);
constructor() public{
x=0;
}
function increment() public {
x.add(1);
emit incremented(x);
}
function get() external view returns (uint) {
return x;
}
}
Expected output is an increment by one on every call to the function but getting the same value every time. Emit also shows the same value.
Well, it's your bug :)
Instead of x.add(1) try x = x.add(1). Add function is not inplace, new value is returned and you need to assign the new value to x.

solidity, set value to state Variables, the value not changed

I'm trying to change the state variable value of solidity, and test on the geth console, but the value of state variable is not changed.
The steps are as below:
1: Write a simple smart contract code by solidity as below
pragma solidity ^0.4.0;
contract SimpleStorage {
uint public storedData=99;
mapping(string => uint) balances;
function set(uint x) public returns (uint){
storedData = x;
return storedData;
}
function get() public constant returns (uint) {
return storedData;
}
function multiply(uint a) returns(uint d) {
return a * 7;
}
function setmapping(string key,uint value) returns(uint v)
{
balances[key] = value;
return balances[key];
}
function getmapping(string key) returns(uint v)
{
return balances[key];
}
function kill()
{
}
}
2: compile the code by the truffle, use command
truffle compile
3:start the geth, unlock account, and start the minner
4:deploy the smart contract
truffle migration --reset
and then I see the console output as below
Using network 'development'.
Running migration: 1_initial_migration.js
Replacing Migrations...
... 0x8ccf9e1599c2760ff3eed993be10929403e1faa05489a247a067f4f06536c74c
Migrations: 0xec08113a9e810e527d99a1aafa8376425c4a75ed
Saving successful migration to network...
... 0xedbf12715b736759e9d9297cbaaeb3151d95f478c2f1ee71bff4819d2dbb47e5
Saving artifacts...
Running migration: 2_deploy_contracts.js
Replacing SimpleStorage...
... 0xff5b00f9b14d8ecea4828c3ad8e9dbfa9d685bc0b81530fc346759d7998b060f
SimpleStorage: 0x96cf1e076f4d99a5d0823bd76c8de6a3a209d125
Saving successful migration to network...
... 0x3452a9e76b73e250de80874ebc3fd454724ebf6a15563bee0d5ba89b7b41909f
Saving artifacts...
which means the smart contract deployed to geth successfully
5: Then in the geth console, I set abi variable as below:
abi=[{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"changeStorage","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getAll","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"key","type":"string"},{"name":"value","type":"uint256"}],"name":"setmapping","outputs":[{"name":"v","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"refrenceType","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"changeMemory","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"key","type":"string"}],"name":"getmapping","outputs":[{"name":"v","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"type":"function"}]
6: Get an contract instant as below:
test=eth.contract(abi).at("0x2f3970e8e4e2f5ed4ccb37b0f79fe5598700e2f0")
7: Run the set()
test.set.call(22);
The out put is 22, which I think the state variable storedData was successfully set to the new value 22, but when I run below code to read the storedData,
test4.get()
the return value is still 99, which mean the value of storedData was not changed, beside use the uint to do the testing, I also tried the mapping, but the answer is as same as uint, I don't know if I was wrong in somewhere or the state variable is not allowed to be modified, could anyone help me?
Thanks.
From the question, this is the call that is not changing state:
test.set.call(22)
In order to change state, you must issue a transaction. A call(...) only tells you what would happen if you were to send a transaction. For more background, see: What is the difference between a transaction and a call?
So you can replace the above line with:
test.set.sendTransaction(22)
Alternatively, web3.js will automatically attempt to decide whether to use a transaction or a call. So in this case you can use simply:
test.set(22)
For more background on how web3.js decides, see: How does web3.js decide to run a call() or sendTransaction() on a method call?