I have the following ERC-20 Contract:
contract FNFToken is ERC20, ERC20Burnable, Ownable, IERC721Receiver
{
constructor() ERC20("FNFToken", "FNT") {}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
and the following ERC-721 Contract:
contract FractionalNFT is ERC721, ERC721Enumerable, ERC721URIStorage, Pausable, Ownable, ERC721Burnable,IERC721Receiver {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
struct _fnft{
uint256 tokenId;
address fractionalToken;
}
mapping(uint256 => _fnft) public FNFT;
constructor() ERC721("FractionalNFT", "FNFT") {}
function safeMint(address to) public onlyOwner {
_safeMint(to, _tokenIdCounter.current());
_tokenIdCounter.increment();
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function _baseURI() internal pure override returns (string memory) {
return "";
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
whenNotPaused
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
//is the caller of this function the owner of the NFT?
modifier isNFTOwner(uint256 _tokenURI) {
require(msg.sender == ownerOf(_tokenURI));
_;
}
function transferFNFToken(
address _to,
uint256 _tokenURI,
uint256 _amount)
onlyOwner()
public
// private
//isNFTOwner(_tokenURI)
{
FNFToken _fnftoken = FNFToken(FNFT[_tokenURI].fractionalToken);
_fnftoken.transfer(_to, _amount);
}
function mint(
address _to,
string memory tokenURI_,
uint256 _totalFractionalTokens
) external {
_safeMint(_to, _tokenIdCounter.current());
_setTokenURI(_tokenIdCounter.current(), tokenURI_);
//Create a ERC20 Token Contract for this newly minted NFT
FNFToken _fnftoken = new FNFToken(); //initialize
_fnftoken.mint(_to, _totalFractionalTokens * 1000000000000000000); //now mint the fractional tokens and send it to the owner of this NFT
console.log("To", _to);
_fnft memory fnft; //constructor
fnft.tokenId = _tokenIdCounter.current();
fnft.fractionalToken = address(_fnftoken);
FNFT[_tokenIdCounter.current()] = fnft; //bind the fractional token address to this NFT token just minted
_tokenIdCounter.increment();
}
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
The mint function in this contract creates an ERC-721/FNFT token and mints it, then creates an ERC-20/FNT tokens through FNTToken contract and mints them to the same address as ERC-721. It then binds the ERC-20 Tokens to this ERC-721/FNFT Token.
The problem is after calling the mint function when I call the NFTTransfer function I get the error
"Error: VM Exception while processing transaction: reverted with reason string 'ERC20: transfer amount exceeds balance'"
When I check the balance of the account on which the ERC-20 and ERC-721 tokens are minted it gives me 1 (only the ERC-721/FNFT is getting transferred). I have tried only minting the ERC-20/FNT but the balance of the account is 0 in this case. In the metamask the balance of ERC-20/FNT is displayed as 0.000000000..12. I think there is something wrong while passing the decimal value on this line : _fnftoken.mint(_to, _totalFractionalTokens * 1000000000000000000); //now mint the fractional tokens and send it to the owner of this NFT
But so far I couldn't find the solution.
Following is the test function to to check transfer of the tokens:
describe("transferFNFToken", () => {
it("should transfer tokens correctly", async function () {
await contract1.deployed();
await contract2.deployed();
const [owner, addr1, addr2] = await ethers.getSigners();
console.log("Owner Address",owner.address);
await contract1.connect(owner).mint(owner.address, 'IPFSHASH/0',4);
await contract1.connect(owner).transferFNFToken(addr2.address, 0,1);
const balance = await contract1.connect(owner).balanceOf(owner.address);
console.log("Balanace Owner Account: ",balance);
});
});
When I organized the code as below:
FractionalNFT
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.7;
import "#openzeppelin/contracts#4.6.0/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/IERC721.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts#4.6.0/access/Ownable.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC20/extensions/draft-ERC20Permit.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts#4.6.0/security/Pausable.sol";
import "./FNFToken.sol";
import "hardhat/console.sol";
contract FractionalNFT is ERC721, ERC721Enumerable, ERC721URIStorage, Pausable, Ownable, ERC721Burnable,IERC721Receiver {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
struct _fnft{
uint256 tokenId;
address fractionalToken;
}
mapping(uint256 => _fnft) public FNFT;
constructor() ERC721("FractionalNFT", "FNFT") payable{}
function safeMint(address to) public onlyOwner {
_safeMint(to, _tokenIdCounter.current());
_tokenIdCounter.increment();
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function _baseURI() internal pure override returns (string memory) {
return "";
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
whenNotPaused
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
//is the caller of this function the owner of the NFT?
modifier isNFTOwner(uint256 _tokenURI) {
require(msg.sender == ownerOf(_tokenURI));
_;
}
function transferFNFToken(
address _to,
uint256 _tokenURI,
uint256 _amount)
onlyOwner()
public
// private
//isNFTOwner(_tokenURI)
{
FNFToken _fnftoken = FNFToken(FNFT[_tokenURI].fractionalToken);
_fnftoken.transfer(_to, _amount);
}
function mint(
address _to,
string memory tokenURI_,
uint256 _totalFractionalTokens
) external {
_safeMint(_to, _tokenIdCounter.current());
_setTokenURI(_tokenIdCounter.current(), tokenURI_);
//Create a ERC20 Token Contract for this newly minted NFT
FNFToken _fnftoken = new FNFToken(); //initialize
_fnftoken.mint(_to, _totalFractionalTokens * 1000000000000000000); //now mint the fractional tokens and send it to the owner of this NFT
console.log("To", _to);
_fnft memory fnft; //constructor
fnft.tokenId = _tokenIdCounter.current();
fnft.fractionalToken = address(_fnftoken);
FNFT[_tokenIdCounter.current()] = fnft; //bind the fractional token address to this NFT token just minted
_tokenIdCounter.increment();
}
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
FNFToken
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.7;
import "#openzeppelin/contracts#4.6.0/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/IERC721.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts#4.6.0/access/Ownable.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC20/extensions/draft-ERC20Permit.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts#4.6.0/token/ERC20/extensions/ERC20Burnable.sol";
contract FNFToken is ERC20, ERC20Burnable, Ownable, IERC721Receiver
{
constructor() ERC20("FNFToken", "FNT") {}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
It is throwing the following error:
revert The transaction has been reverted to the initial state. Reason
provided by the contract: "ERC20: transfer amount exceeds balance".
Debug the transaction to get more information.
Probably solution must be like in the following link
https://forum.openzeppelin.com/t/erc20-transferfrom-fails-erc20-transfer-amount-exceeds-balance/16854
Related
I have a contract with the following payable function
Contract Constructor
constructor( address payable _NFT_CONTRACT, address payable _TOKEN_CONTRACT) payable {
NFT_CONTRACT = IERC721(_NFT_CONTRACT);
TOKEN_CONTRACT = IERC20(_TOKEN_CONTRACT);
}
Function Stake:
function stake(uint256[] calldata tokenIds, uint256[] calldata powers) external payable {
for (uint i = 0; i <= tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
uint256 power = powers[i];
require(NFT_CONTRACT.ownerOf(tokenId) == msg.sender, "You can only stake your own token");
require(vault[tokenId].tokenId == 0, "You can only stake once");
NFT_CONTRACT.safeTransferFrom(msg.sender, address(this), tokenId);
vault[tokenId] = Stake({
tokenId: tokenId,
timestamp: block.timestamp,
owner: msg.sender,
power: power
});
userStacks[msg.sender].push(tokenId);
hasPaid[tokenId] = 0;
}
}
vault, userStacks, and hasPaid are all structs.
struct Stake {
address owner;
uint256 tokenId;
uint256 timestamp;
uint256 power;
}
mapping(uint256 => Stake) public vault;
mapping(address => uint256[]) public userStacks;
mapping(uint256 => uint256) public hasPaid;
The problem:
Function stake works perfectly fine if I remove the for loop, but, throws this error if I have the loop:
revert
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.
I am using solidity ^0.8.0;
I test with arrays such as [1,2], [4,5], for both params.
Thanks.
I would like to know if it is possible to generate a unique number for each address, I tried mapping but it does not work
contract RandomNumberConsumer is VRFConsumerBase {
bytes32 internal keyHash;
uint256 internal fee;
uint256 public randomResult;
mapping(address => uint) public random;
constructor()
VRFConsumerBase(
0x8C7382F9D8f56b33781fE506E897a4F1e2d17255, // VRF Coordinator
0x326C977E6efc84E512bB9C30f76E30c160eD06FB // LINK Token
)
{
keyHash = 0x6e75b569a01ef56d18cab6a8e71e6600d6ce853834d4a5748b720d06f878b3a4;
fee = 0.0001 * 10 ** 18; // 0.0001 LINK (Varies by network)
}
function getRandomNumber() public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
random[msg.sender] = randomness;
}
}
here is the mapping
mapping(address => uint) public random;
random[msg.sender] = randomness;
Thanks!
You are close with what you have so far. I've updated the contract a bit and included notes below. The main change was a new mapping to store the request id -> address. This lets the fulfillRandomness function update the correct address -> randomNumber mapping.
pragma solidity ^0.8.0;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract RandomNumberConsumer is VRFConsumerBase {
bytes32 internal keyHash;
uint256 internal fee;
uint256 public randomResult;
// ** New mapping to store requests
mapping(bytes32 => address) public requestIdToAddress;
mapping(address => uint) public random;
constructor()
VRFConsumerBase(
0x8C7382F9D8f56b33781fE506E897a4F1e2d17255, // VRF Coordinator
0x326C977E6efc84E512bB9C30f76E30c160eD06FB // LINK Token
)
{
keyHash = 0x6e75b569a01ef56d18cab6a8e71e6600d6ce853834d4a5748b720d06f878b3a4;
fee = 0.0001 * 10 ** 18; // 0.0001 LINK (Varies by network)
}
function getRandomNumber() public {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
// ** Store the random request in requestID
bytes32 requestId = requestRandomness(keyHash, fee);
// ** Map requestId to the sender's address
requestIdToAddress[requestId] = msg.sender;
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
// ** Find the sender address based on the request
address _sender = requestIdToAddress[requestId];
// ** Update sender's mapping for randomness
random[_sender] = randomness;
}
}
I am following the Large Responses Chainlink tutorial and am receiving an error when trying to call the requestOracleData() function. Everything works fine when using v0.6, but I need to use v0.8 in order to receive large responses.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#chainlink/contracts/src/v0.8/ChainlinkClient.sol";
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
/**
* #title MyContract is an example contract which requests data from
* the Chainlink network
* #dev This contract is designed to work on multiple networks, including
* local test networks
*/
contract MyContract is ChainlinkClient, ERC721 {
using Chainlink for Chainlink.Request;
// address constant ORACLE = 0xF405B99ACa8578B9eb989ee2b69D518aaDb90c1F;
// bytes32 constant JOB_ID = bytes32("7c4b968028f74b2eabd7d428f03ba45c");
address constant RINKEBY_ORACLE =
0x3A56aE4a2831C3d3514b5D7Af5578E45eBDb7a40;
bytes32 constant RINKEBY_JOB_ID =
bytes32("187bb80e5ee74a139734cac7475f3c6e");
uint256 constant FEE = 0.1 * 10**18;
bytes32 internal keyHash;
uint256 public fee;
uint256 public tokenCounter;
// bytes public data;
bytes32 public data;
string public image_url;
struct Clip {
string name;
string url;
}
Clip[] public clips;
mapping(bytes32 => string) public requestIdToClipName;
mapping(bytes32 => address) public requestIdToSender;
mapping(bytes32 => string) public requestIdToTokenURI;
event requestedCollectible(bytes32 indexed requestId);
mapping(bytes32 => uint256) public requestToTokenId;
mapping(uint256 => string) public tokenIdToName;
mapping(uint256 => string) public tokenIdToImgUrl;
constructor(address _link) public ERC721("Tests", "TST") {
if (_link == address(0)) {
setPublicChainlinkToken();
} else {
setChainlinkToken(_link);
}
setChainlinkOracle(0x3A56aE4a2831C3d3514b5D7Af5578E45eBDb7a40);
tokenCounter = 0;
}
function getChainlinkToken() public view returns (address) {
return chainlinkTokenAddress();
}
function createRequestTo(
string memory _url,
string memory _path,
string memory clipName
) public returns (bytes32 requestId) {
Chainlink.Request memory req = buildChainlinkRequest(
RINKEBY_JOB_ID,
address(this),
this.fulfill.selector
);
req.add("get", _url);
req.add("path", _path);
requestOracleData(req, FEE);
requestId = sendChainlinkRequestTo(RINKEBY_ORACLE, req, FEE);
requestIdToClipName[requestId] = clipName;
requestIdToSender[requestId] = msg.sender;
emit requestedCollectible(requestId);
return requestId;
}
function fulfill(bytes32 _requestId, bytes32 _data)
public
recordChainlinkFulfillment(_requestId)
{
address nftOwner = requestIdToSender[_requestId];
string memory name = requestIdToClipName[_requestId];
uint256 newItemId = clips.length;
data = _data;
image_url = bytes32ToString(data);
clips.push(Clip(name, image_url));
_safeMint(nftOwner, newItemId);
tokenIdToName[newItemId] = name;
tokenIdToImgUrl[newItemId] = image_url;
}
function getNumberOfClips() public view returns (uint256) {
return clips.length;
}
/**
* #notice Allows the owner to withdraw any LINK balance on the contract
*/
function withdrawLink() public {
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
require(
link.transfer(msg.sender, link.balanceOf(address(this))),
"Unable to transfer"
);
}
/**
* #notice Call this method if no response is received within 5 minutes
* #param _requestId The ID that was generated for the request to cancel
* #param _payment The payment specified for the request to cancel
* #param _callbackFunctionId The bytes4 callback function ID specified for
* the request to cancel
* #param _expiration The expiration generated for the request to cancel
*/
function cancelRequest(
bytes32 _requestId,
uint256 _payment,
bytes4 _callbackFunctionId,
uint256 _expiration
) public {
cancelChainlinkRequest(
_requestId,
_payment,
_callbackFunctionId,
_expiration
);
}
function bytes32ToString(bytes32 _bytes32)
public
pure
returns (string memory)
{
uint8 i = 0;
while (i < 32 && _bytes32[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
}
Here is the error I am getting:
Running 'scripts/request_data.py::main'...
File "brownie/_cli/run.py", line 49, in main
return_value, frame = run(
File "brownie/project/scripts.py", line 103, in run
return_value = f_locals[method_name](*args, **kwargs)
File "./scripts/request_data.py", line 18, in main
apicall = my_contract.createRequestTo(URL, PATH, "test", {"from": dev})
File "brownie/network/contract.py", line 1693, in __call__
return self.transact(*args)
File "brownie/network/contract.py", line 1566, in transact
return tx["from"].transfer(
File "brownie/network/account.py", line 642, in transfer
receipt, exc = self._make_transaction(
File "brownie/network/account.py", line 725, in _make_transaction
raise VirtualMachineError(e) from None
File "brownie/exceptions.py", line 121, in __init__
raise ValueError(str(exc)) from None
ValueError: Gas estimation failed: 'execution reverted: Must use whitelisted functions'. This transaction will likely revert. If you wish to broadcast, you must set the gas limit manually.
Note: this error doesn't occur when I comment out the requestOracleData() function.
It is due to the fact that the node operator you are using on Rinkeby isn't set up to handle large requests and is most likely using the Oracle.sol code as their oracle contract, which doesn't accept the requestOracleData() method.
You can either switch to Kovan and use the node given in the docs, search for a different but compatible node on market.link, or host your own node on Rinkeby which is compatible with this job.
This is the documentation of my used API.
The price is still showing 0 as you can see in this image reference.
Here is my code:
pragma solidity ^0.6.0;
import "#chainlink/contracts/src/v0.6/ChainlinkClient.sol";
contract APIConsumer is ChainlinkClient {
event below20(uint _price);
event below30(uint _price);
event below40(uint _price);
event below50(uint _price);
uint256 public Price;
address private oracle;
bytes32 private jobId;
uint256 private fee;
constructor() public {
setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB);
oracle = 0xb33D8A4e62236eA91F3a8fD7ab15A95B9B7eEc7D;
jobId = "da20aae0e4c843f6949e5cb3f7cfe8c";
fee = 10 ** 16; // 0.01 LINK
}
function requestBTCCNYPrice() 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://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=BTC&to_currency=CNY&apikey=demo");
string[] memory path = new string[](2);
path[0] = "Realtime Currency Exchange Rate";
path[1] = "5. Exchange Rate";
request.addStringArray("path", path);
request.addInt("times", 10000000000);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of uint256
*/
function fulfill(bytes32 _requestId, uint256 _price) public recordChainlinkFulfillment(_requestId)
{
Price = _price;
}
That node is down. Use the following node and JobID in this code:
pragma solidity ^0.6.0;
import "#chainlink/contracts/src/v0.6/ChainlinkClient.sol";
contract APIConsumer is ChainlinkClient {
event below20(uint _price);
event below30(uint _price);
event below40(uint _price);
event below50(uint _price);
uint256 public Price;
address private oracle;
bytes32 private jobId;
uint256 private fee;
constructor() public {
setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB);
oracle = 0xc8D925525CA8759812d0c299B90247917d4d4b7C;
jobId = "bbf0badad29d49dc887504bacfbb905b";
fee = 10 ** 16; // 0.01 LINK
}
function requestBTCCNYPrice() 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://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=BTC&to_currency=CNY&apikey=demo");
string[] memory path = new string[](2);
path[0] = "Realtime Currency Exchange Rate";
path[1] = "5. Exchange Rate";
request.addStringArray("path", path);
request.addInt("times", 10000000000);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of uint256
*/
function fulfill(bytes32 _requestId, uint256 _price) public recordChainlinkFulfillment(_requestId)
{
Price = _price;
}
}
To check to see if a node is running or not, check out the oracle address in a block explorer. You can see here that the original node you tried to use hasn't posted a transaction in quite a long time.
To find nodes and jobs that are currently working, you should check market.link.
I am creating nft smart contract and using chainlinkClient.sol for updation of URI.
chainlinkClient Version: v0.6
Error: TypeError: Member "add" not found or not visible after argument-dependent lookup in struct Chainlink.Request memory.
Any Idea Why am I getting this error?
Code:
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
import "chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";
contract phoneNumber is ChainlinkClient{
uint256 public phone_no;
address private oracle;
bytes32 private jobId;
uint256 private fee;
constructor(uint256 _initial_phone_no){
setPublicChainlinkToken();
oracle = 0x7AFe1118Ea78C1eae84ca8feE5C65Bc76CcF879e;
jobId = "6d1bfe27e7034b1d87b5270556b17277";
fee = 0.1 * 10 ** 18; // 0.1 LINK
phone_no = _initial_phone_no;
}
function requestVolumeData() public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.update_phone_no.selector);
// Set the URL to perform the GET request on
request.add("get", "http://localhost:3000/images/phone.json");
request.add("path", "phone.new");
// Multiply the result by 1000000000000000000 to remove decimals
int timesAmount = 10**18;
request.addInt("times", timesAmount);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
function update_phone_no(bytes32 _requestId, uint256 new_phone_no) public recordChainlinkFulfillment(_requestId)
{
phone_no = new_phone_no;
}
function withdrawLink() external {
LinkTokenInterface linkToken = LinkTokenInterface(chainlinkTokenAddress());
require(linkToken.transfer(msg.sender, linkToken.balanceOf(address(this))), "Unable to transfer");
}
}
Your import statement is missing an "#" symbol. Add it to the beginning like this:
import "#chainlink/contracts/src/v0.6/ChainlinkClient.sol";
Note: Also don't forget to explicitly state your constructor visibility specifier to public or internal as well.