Coder Social home page Coder Social logo

functions-hardhat-starter-kit's Introduction

Chainlink Functions Starter Kit

Overview

Chainlink Functions allows users to request data from HTTP(s) APIs and perform custom computation using JavaScript. It works by executing the request on a decentralized oracle network (DON). When a request is initiated, each node in the DON executes the user-provided JavaScript code simultaneously. Then, nodes use the Chainlink OCR protocol to come to consensus on the results. Finally, the median result is returned to the requesting contract via a callback function.

Chainlink Functions also enables users to securely share secrets with the DON, allowing users to access APIs that require authentication without exposing their API keys. Secrets are encrypted with threshold public key cryptography, requiring multiple nodes to participate in a decentralized decryption process such that no node can decrypt secrets without consensus from the rest of the DON.

Nodes are compensated in LINK via a subscription billing model. You can see billing details here and pricing for each network here.

Working with Chainlink Functions requires accepting the terms of service before you are able to create a subscription. Please visit chain.link/functions.

Motivation

This repo provides developers with a "works out of the box" experience as it comes preconfigured with dependencies and popular tooling like Hardhat. This is not a tutorial for the Hardhat toolchain. It assumes basic familiarity with Hardhat and the command line. We use HardHat CLI scripts to run Chainlink Functions commands and operations.

In order to set up your own project which uses Chainlink Functions, please refer to the Functions Toolkit NPM package.

Supported Networks

⚠️⚠️⚠️ As at 13 April 2024, Mumbai (anchored to Goerli) stopped producing blocks. Mumbai's deprecation had been announced in favour of a new Amoy testnet, anchored to Sepolia.

Mainnets

  • Ethereum : ETHEREUM_RPC_URL, --network ethereum, ETHERSCAN_API_KEY
  • Polygon : POLYGON_RPC_URL, --network polygon, POLYGONSCAN_API_KEY
  • Avalanche : AVALANCHE_RPC_URL, --network avalanche, SNOWTRACE_API_KEY
  • Arbitrum : ARBITRUM_RPC_URL, --network arbitrum, ARBISCAN_API_KEY
  • Base : BASE_RPC_URL, --network base, BASESCAN_API_KEY
  • Celo : CELO_RPC_URL, --network celo, CELOSCAN_API_KEY

Testnets

  • Ethereum Sepolia: ETHEREUM_SEPOLIA_RPC_URL, --network ethereumSepolia, ETHERSCAN_API_KEY
  • Polygon Amoy: POLYGON_AMOY_RPC_URL, --network polygonAmoy, POLYGONSCAN_API_KEY
  • Avalanche Fuji: AVALANCHE_FUJI_RPC_URL, --network avalancheFuji, SNOWTRACE_API_KEY
  • Arbitrum Sepolia: ARBITRUM_SEPOLIA_RPC_URL, --network arbitrumSepolia, ARBISCAN_API_KEY
  • Base Sepolia: BASE_SEPOLIA_RPC_URL, --network baseSepolia, BASESCAN_API_KEY
  • Optimism Sepolia: OPTIMISM_SEPOLIA_RPC_URL, --network optimismSepolia, OP_ETHERSCAN_API_KEY
  • Celo Alfajores: CELO_ALFAJORES_RPC_URL, --network celoAlfajores, CELOSCAN_API_KEY

For Beginners

If you're new to web3, it is recommended starting with the Functions - Getting Started guide before diving into the code.

The above document will help you:

  • Set up a wallet
  • Get funds
  • Provides more detailed step-by-step instructions and further information

Tutorials & examples

For other detailed tutorials and examples, check out the Chainlink Functions Tutorials to get started.

Quickstart

Requirements

Install both of the following:

  • Node.js version 20
  • Deno version 1.36 (or the latest release of Deno v1 if a later one is available)

Steps on Live (Public) Testnets

  1. Clone this repository to your local machine

    . Also ensure that the testnet your wanting to deploy on is supported by Chainlink Functions.

  2. Open this directory in your command line/terminal app, then run npm install to install all dependencies.

  3. Obtain the values for following environment variables (examples only - please see ./env.enc.example for env vars you may need):

    • PRIVATE_KEY for your development wallet - POLYGON_AMOY_RPC_URL, ETHEREUM_SEPOLIA_RPC_URL, or AVALANCHE_FUJI_RPC_URL
    • POLYGONSCAN_API_KEY, ETHERSCAN_API_KEY, or FUJI_SNOWTRACE_API_KEY blockchain explore API keys depending on which network you're using
    • COINMARKETCAP_API_KEY (from here)

  4. Set the required environment variables (see ./env.enc.example for the correctly capitalized names of environment variables used in this repo). For improved security, Chainlink provides the NPM package @chainlink/env-enc which can be used to keep environment variables in a password encrypted .env.enc file instead of a plaintext .env for additional security. More detail on environment variable management and the tooling is provided in the Environment Variable Management section.

    1. Set an encryption password for your environment variables to a secure password by running npx env-enc set-pw. This password needs to be set each time you create or restart a terminal shell session.
    2. Use the command npx env-enc set to set the required environment variables.
    3. Set any other values you intend to pass into the secrets object in Functions-request-config.js .

  5. There are four files to notice that the default example will use:

    • Functions-request-config.js which contains the request object that has all the data necessary to trigger a Functions request. This config file also specifies which source code to pass to Functions. More information on request configuration is in the Request Configuration section.
    • contracts/FunctionsConsumer.sol is the consumer smart contract that will receive the Functions-related data from the request config, and trigger the functions request.
    • calculation-example.js contains example JavaScript code that will be executed by each node of the DON. This example performs complex calculations but no API requests.
    • API-request-example.js contains example JavaScript code which fetches data from APIs before processing the data

  6. Locally simulate the execution of your JavaScript source by running npx hardhat functions-simulate-script

  7. Deploy and verify the consumer contract to an actual blockchain network by running npx hardhat functions-deploy-consumer --network network_name_here --verify true
    Note: Make sure <explorer>_API_KEY is set if using --verify true depending on which network is used.

  8. Create and fund a new Functions billing subscription using the Chainlink Functions UI and add the deployed consumer contract as an authorized consumer to your subscription. You can also do this programmatically with npx hardhat functions-sub-create --network network_name_here --amount LINK_funding_amount_here --contract 0x_deployed_client_contract_address_here
    Note: Ensure your wallet has a sufficient LINK balance before running this command. Testnet LINK can be obtained at faucets.chain.link. Also make a note of your subscription Id as you will need it for most commands.

  9. Make an on-chain request by running:
    npx hardhat functions-request --network network_name_here --contract 0xDeployed_client_contract_address_here --subid subscription_id_number_here. You will see a confirmation request, so hit Y and press enter. Once the request is fulfilled the console will show the response (decoded into the relevant return type) from the execution of your custom JS script.

  10. You can also query the response that was stored in your Functions Consumer contract by runnning npx hardhat functions-read --contract 0xConsumer_contract_address --network your_network_name

Steps on local testnet

  1. To do an end-to-end simulation using a local testnet you can first open a new terminal window and run npm run startLocalFunctionsTestnet. This will spin up a local blockchain testnet (the localFunctionsTestnet), on which you can simulate an end-to-end Functions request.

  2. Follow the workflow steps above, including subscription creation, funding, deploying your Functions Consumer etc. but omit the --network network_name_here flag in your CLI commands as the default network will be the localFunctionsTestnet.

  3. Running this end-to-end simulation will surface most errors in your smart contract and/or JavaScript source code and configuration.

Environment Variable Management

This repo uses the NPM package @chainlink/env-enc for keeping environment variables such as wallet private keys, RPC URLs, and other secrets encrypted at rest. This reduces the risk of credential exposure by ensuring credentials are not visible in plaintext as they are with .env files.

By default, all encrypted environment variables will be stored in a file named .env.enc in the root directory of this repo. This file is .gitignore'd.

For a full list of the Env Var names (keys) that this repo uses and has defined please look at ./env.enc.example.

First, set the encryption password by running the command npx env-enc set-pw.

NOTE: On Windows, this command may show a security confirmation.

The password must be set at the beginning of each new session. If this password is lost, there will be no way to recover the encrypted environment variables.

Run the command npx env-enc set to set and save environment variables. These variables will be loaded into your environment when the config() method is called at the top of networks.js.

Use npx env-enc view to view all currently saved environment variables. When pressing ENTER, the terminal will be cleared to prevent these values from remaining visible.

Running npx env-enc remove VAR_NAME_HERE deletes the specified environment variable.

The command npx env-enc remove-all deletes the entire saved environment variable file.

When running this command on a Windows machine, you may receive a security confirmation prompt. Enter r to proceed.

NOTE: When you finish each work session, close down your terminal to prevent your encryption password from becoming exposes if your machine is compromised. You will need to set the same password on future session to decrypt the .env.enc file.

Using Remote Secrets (e.g. Github Gists)

To upload and delete secrets gists that will remotely store your encrypted secrets, you need to first acquire a Github personal access token which allows reading and writing Gists.

  1. Visit https://github.com/settings/tokens?type=beta and click "Generate new token"
  2. Name the token and enable read & write access for Gists from the "Account permissions" drop-down menu. Do not enable any additional permissions.
  3. Click "Generate token" and copy the resulting personal access token for step 4.
  4. set the GITHUB_API_TOKEN environment variable using npx env-enc set
  5. Specify Location.Remote for the secretLocation in Functions-request-config.js

Environment Variable Management Commands

The following commands accept an optional --path flag followed by a path to the desired encrypted environment variable file. If one does not exist, it will be created automatically by the npx env-enc set command.

The --path flag has no effect on the npx env-enc set-pw command as the password is stored as an ephemeral environment variable for the current terminal session.

Command Description Parameters
npx env-enc set-pw Sets the password to encrypt and decrypt the environment variable file NOTE: On Windows, this command may show a security confirmation prompt
npx env-enc set Sets and saves variables to the encrypted environment variable file
npx env-enc view Shows all currently saved variables in the encrypted environment variable file
npx env-enc remove <name> Removes a variable from the encrypted environment variable file name: Variable name
npx env-enc remove-all Deletes the encrypted environment variable file

Functions Command Glossary

Functions Commands and Subscription Management Commands commands can be executed in the following format: npx hardhat command_here --parameter1 parameter_1_value_here --parameter2 parameter_2_value_here

Example: npx hardhat functions-read --network polygonMumbai --contract 0x787Fe00416140b37B026f3605c6C72d096110Bb8

Functions Commands

Command Description Parameters
compile Compiles all smart contracts
functions-simulate-script Executes the JavaScript source code locally network: Name of blockchain network, configpath (optional): Path to request config file (defaults to ./Functions-request-config.js)
functions-deploy-consumer Deploys the FunctionsConsumer contract network: Name of blockchain network, verify (optional): Set to true to verify the deployed FunctionsConsumer contract (defaults to false)
functions-request Initiates a request from a FunctionsConsumer contract using data from the Functions request config file network: Name of blockchain network, contract: Address of the consumer contract to call, subid: Billing subscription ID used to pay for the request, callbackgaslimit (optional): Maximum amount of gas that can be used to call fulfillRequest in the consumer contract (defaults to 100,000 & must be less than 300,000), slotid (optional): Slot ID to use for uploading DON hosted secrets. If the slot is already in use, the existing encrypted secrets will be overwritten. (defaults to 0), simulate (optional, default true): Flag indicating if simulation should be run before making an on-chain request, requestgaslimit (optional): Gas limit for calling the sendRequest function (defaults to 1,500,000) configpath (optional): Path to request config file (defaults to ./Functions-request-config.js)
functions-read Reads the latest response (or error) returned to a FunctionsConsumer or AutomatedFunctionsConsumer contract network: Name of blockchain network, contract: Address of the consumer contract to read, configpath (optional): Path to request config file (defaults to ./Functions-request-config.js)
functions-deploy-auto-consumer Deploys the AutomatedFunctionsConsumer contract and sets the Functions request using data from the Functions request config file network: Name of blockchain network, subid: Billing subscription ID used to pay for Functions requests, verify (optional, default false): Set to true to verify the deployed AutomatedFunctionsConsumer contract, configpath (optional): Path to request config file (defaults to ./Functions-request-config.js)
functions-set-auto-request Updates the Functions request in deployed AutomatedFunctionsConsumer contract using data from the Functions request config file network: Name of blockchain network, contract: Address of the contract to update, subid: Billing subscription ID used to pay for Functions requests, interval (optional): Update interval in seconds for Chainlink Automation to call performUpkeep (defaults to 300), slotid (optional) 0 or higher integer denoting the storage slot for DON-hosted secrets, ttl (optional) the minutes after which DON hosted secrets must be expired, gaslimit (optional): Maximum amount of gas that can be used to call fulfillRequest in the consumer contract (defaults to 250,000), simulate (optional, default true): Flag indicating if simulation should be run before making an on-chain request, configpath (optional): Path to request config file (defaults to ./Functions-request-config.js)
functions-check-upkeep Checks if checkUpkeep returns true for an Automation compatible contract network: Name of blockchain network, contract: Address of the contract to check, data (optional): Hex string representing bytes that are passed to the checkUpkeep function (defaults to empty bytes)
functions-perform-upkeep Manually call performUpkeep in an Automation compatible contract network: Name of blockchain network, contract: Address of the contract to call, data (optional): Hex string representing bytes that are passed to the performUpkeep function (defaults to empty bytes)
functions-set-donid Updates the DON ID for a consumer contract using the donId address from networks.js network: Name of blockchain network, contract: Address of the consumer contract to update
functions-build-request Creates a JSON file with Functions request parameters including encrypted secrets, using data from the Functions request config file network: Name of blockchain network, output (optional): Output JSON file name (defaults to Functions-request.json), simulate (optional, default true): Flag indicating if simulation should be run before building the request JSON file, configpath (optional): Path to request config file (defaults to ./Functions-request-config.js)
functions-build-offchain-secrets Builds an off-chain secrets object that can be uploaded and referenced via URL network: Name of blockchain network, output (optional): Output JSON file name (defaults to offchain-encrypted-secrets.json), configpath (optional): Path to request config file (defaults to ./Functions-request-config.js)
functions-upload-secrets-don Encrypts secrets and uploads them to the DON network: Name of blockchain network, configpath (optional): Path to request config file (defaults to ./Functions-request-config.js), slotid Storage slot number 0 or higher - if the slotid is already in use, the existing secrets for that slotid will be overwritten, ttl (optional): Time to live - minutes until the secrets hosted on the DON expire (defaults to 10, and must be at least 5)
functions-list-don-secrets Displays encrypted secrets hosted on the DON network: Name of blockchain network

Functions Subscription Management Commands

Command Description Parameters
functions-sub-create Creates a new Functions billing subscription for Functions consumer contracts network: Name of blockchain network, amount (optional): Initial amount used to fund the subscription in LINK (decimals are accepted), contract (optional): Address of the consumer contract to add to the subscription
functions-sub-info Gets the Functions billing subscription balance, owner, and list of authorized consumer contract addresses network: Name of blockchain network, subid: Subscription ID
functions-sub-fund Funds a Functions billing subscription with LINK network: Name of blockchain network, subid: Subscription ID, amount: Amount to fund subscription in LINK (decimals are accepted)
functions-sub-cancel Cancels a Functions billing subscription and refunds the unused balance. Cancellation is only possible if there are no pending requests. network: Name of blockchain network, subid: Subscription ID, refundaddress (optional): Address where the remaining subscription balance is sent (defaults to caller's address)
functions-sub-add Authorizes a consumer contract to use the Functions billing subscription network: Name of blockchain network, subid: Subscription ID, contract: Address of the consumer contract to authorize for billing
functions-sub-remove Removes a consumer contract from a Functions billing subscription network: Name of blockchain network, subid: Subscription ID, contract: Address of the consumer contract to remove from billing subscription
functions-sub-transfer Request ownership of a Functions subscription be transferred to a new address network: Name of blockchain network, subid: Subscription ID, newowner: Address of the new owner
functions-sub-accept Accepts ownership of a Functions subscription after a transfer is requested network: Name of blockchain network, subid: Subscription ID
functions-timeout-requests Times out expired Functions requests which have not been fulfilled within 5 minutes network: Name of blockchain network, requestids: 1 or more request IDs to timeout separated by commas, toblock (optional): Ending search block number (defaults to latest block), pastblockstosearch (optional): Number of past blocks to search (defaults to 1,000)

Request Configuration

Chainlink Functions requests can be configured by modifying values in the requestConfig object found in the Functions-request-config.js file located in the root of this repository.

Setting Name Description
codeLocation This specifies where the JavaScript code for a request is located. Currently, only the Location.Inline option is supported (represented by the value 0). This means the JavaScript string is provided directly in the on-chain request instead of being referenced via a URL.
codeLanguage This specifies the language of the source code which is executed in a request. Currently, only JavaScript is supported (represented by the value 0).
source This is a string containing the source code which is executed in a request. This must be valid JavaScript code that returns a Uint8Array. See the JavaScript Code section for more details.
secrets This is an (optional) object which contains secret values that are injected into the JavaScript source code and can be accessed using the name secrets. This object can only contain string values. This object will be automatically encrypted by the tooling using the threshold public key before making request.
secretsLocation This (optional) value must be present if secrets are present. Values must be one of either DONhosted or Remote. This refers to the location of the Secrets - which can be User-hosted (Remote) at a URL or DON-hosted.
args This is an array of strings which contains values that are injected into the JavaScript source code and can be accessed using the name args. This provides a convenient way to set modifiable parameters within a request. If no arguments, then an empty array is passed.
expectedReturnType This specifies the expected return type of a request. It has no on-chain impact, but is used by the CLI to decode the response bytes into the specified type. The options are uint256, int256, string, or bytes.

JavaScript Code

The JavaScript source code for a Functions request can use any valid Deno JavaScript, but cannot use any imported modules.

The code must return a Uint8Array which represents the response bytes that are sent back to the requesting contract. Encoding functions are provided in the Functions library. Additionally, any external APIs to which requests are made must script must respond in less than 9 seconds and the JavaScript Code as a whole must return in less than 10 seconds or it will be terminated and send back an error (in bytes) to the requesting contract.

In order to make HTTP requests, the source code must use the Functions.makeHttpRequest function from the exposed Functions library. Asynchronous code with top-level await statements is supported, as shown in the file API-request-example.js.

Functions Library

The Functions library is injected into the JavaScript source code and can be accessed using the name Functions.

In order to make HTTP requests, use the Functions.makeHttpRequest method which takes an object as an argument with the following parameters.

{
  url: String with the URL to which the request is sent,
  method (optional): String specifying the HTTP method to use which can be either 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', or 'OPTIONS' (defaults to 'GET'),
  headers (optional): Object with headers to use in the request,
  params (optional): Object with URL query parameters,
  data (optional): Object or other value which represents the body sent with the request,
  timeout (optional): Number with the maximum request duration in ms (defaults to 3000 ms),
  responseType (optional): String specifying the expected response type which can be either 'json', 'arraybuffer', 'document', 'text' or 'stream' (defaults to 'json'),
}

The function returns a promise that resolves to either a success response object or an error response object.

A success response object will have the following parameters.

{
  error: false,
  data: Response data sent by the server,
  status: Number representing the response status,
  statusText: String representing the response status,
  headers: Object with response headers sent by the server,
}

An error response object will have the following parameters.

{
  error: true,
  message (may be undefined): String containing error message,
  code (may be undefined): String containing an error code,
  response (may be undefined): Object containing response sent from the server,
}

This library also exposes functions for encoding JavaScript values into Uint8Arrays which represent the bytes that a returned on-chain.

  • Functions.encodeUint256 takes a positive JavaScript integer number and returns a Uint8Array of 32 bytes representing a uint256 type in Solidity.
  • Functions.encodeInt256 takes a JavaScript integer number and returns a Uint8Array of 32 bytes representing a int256 type in Solidity.
  • Functions.encodeString takes a JavaScript string and returns a Uint8Array representing a string type in Solidity.

Remember, it is not required to use these encoding functions. The JavaScript code must only return a Uint8Array which represents the bytes that are returned on-chain.

Importing Dependencies

To import and use libraries in your Functions request JavaScript source code, you must use the async import function. Since this is an async function, you must remember to use the await keyword to wait for the dependency to be imported before it can be used as shown in the examples below.

const lodash = await import("http://cdn.skypack.dev/lodash");
const result = lodash.concat([1], 2);
return Functions.encodeString(JSON.stringify(result));
const { ethers } = await import("npm:[email protected]");
const myNumber = ethers.AbiCoder.defaultAbiCoder().decode(
  ["uint256"],
  "0x000000000000000000000000000000000000000000000000000000000000002a"
);
return Functions.encodeUint256(BigInt(myNumber.toString()));

⚠️ Users are fully responsible for any dependencies their JavaScript source code imports. Chainlink is not responsible for any imported dependencies and provides no guarantees of the validity, availability or security of any libraries a user chooses to import or the repositories from which these dependencies are downloaded. Developers are advised to fully vet any imported dependencies or avoid dependencies altogether to avoid any risks associated with a compromised library or a compromised repository from which the dependency is downloaded.

Chainlink Functions supports importing ESM-compatible modules with are supported by Deno within the JavaScript source code. It also supports importing some NPM packages via the npm: specifier and some standard Node.js modules via the node: specifier. Check out the Deno documentation on importing modules for more information or visit deno.land/x to find 3rd party modules which have been built for Deno.

The total number of imports and the size of each import are restricted:

  • You can import a maximum of 100 dependencies. Sub-dependencies required by the target library also count toward this limit.
  • The total size of each imported dependency cannot be larger than 10 MB. This 10 MB size limit includes any sub-dependencies required by the target library.

All other service limits still apply to imported dependencies. This means the dependencies will not have access to the file system, environment variables or any other Deno permissions. If an imported library requires restricted permissions, importing the library may result in an error. Furthermore, dependencies are downloaded at runtime, meaning the time required to download a dependency is counted toward the total JavaScript source code execution time limit.

Sometimes imported dependencies use additional fetch requests to load additional code or resources. These fetch requests count toward the total number of HTTP requests that the JavaScript source code is allowed to perform. If the imported dependencies exceed this total number of allowed fetch requests, the import attempt will fail with an error.

Modifying Contracts

Consumer contracts which initiate a request and receive a fulfillment can be modified for specific use cases. The only requirements are that the contract successfully calls sendRequest in the FunctionsRouter, and that it correctly implements the fulfillRequest function which is called by handleOracleFulfillment in the inherited FunctionsClient contract (See FunctionsClient.sol for details).
At this time, the maximum amount of gas that handleOracleFulfillment can use is 300,000 (please contact Chainlink Labs if you require a higher callback gas limit).

Local Simulations with the localFunctionsTestnet

The Functions Toolkit NPM package provides the ability to create a local testnet blockchain on your machine which allows you to make simulated requests to debug your JavaScript code and smart contracts. For more details, please see the Functions Toolkit NPM package documentation.

In order to launch the localFunctionsTestnet in this project, open a new terminal window and run the command npm run startLocalFunctionsTestnet. Then, you can interact with this local testnet blockchain as you would with a live testnet.

By default, all the npx hardhat commands in this project are configured to use this local testnet running on port 8545, so you can omit the --network CLI argument (just don't forget to start the testnet first).

Managing Secrets

Please refer to the Functions Toolkit NPM package documentation for more details.

Secrets can be managed in either of two ways: user-hosted (Location.Remote) or DON hosted (Location.DONHosted).

This project uses DONHosted secrets by default, which means secrets from the Functions-request-config.js file are encrypted and then uploaded to the DON and automatically.

The CLI command to upload secrets to the DON is npx hardhat functions-upload-secrets-don --slotid _0_or_higher --network network_name --ttl minutes_until_expired.

Automation Integration

Chainlink Functions can be used with Chainlink Automation in order to automatically trigger a Functions as specified intervals.

  1. Create & fund a new Functions billing subscription by running npx hardhat functions-sub-create --network network_name_here --amount LINK_funding_amount_here
    Note: Ensure your wallet has a sufficient LINK balance before running this command.

  2. Deploy the AutomationFunctionsConsumer contract by running npx hardhat functions-deploy-auto-consumer --subid subscription_id_number_here --verify true --network network_name_here
    Note: Make sure <blockexplorer>_API_KEY environment variable is set when using --verify true.

    • This step will automatically add your consumer contract as an authorized user of your subscription. You can verify by running npm functions-sub-info --network network_name_here --subid subscription_id_number_here.
  3. Encode the request parameters into CBOR and store it on chain with npx hardhat functions-set-auto-request --network network_name_here --subid subscription_id_number_here --interval automation-call-interval --slotid don_hosted_secret_slotId --ttl minutes_until_secrets_expiry --contract 0x_contract_address

DON-Hosted secrets and expire after the specified ttl (which defaults to 10 minutes if no ttl is specified). If a request is sent after the ttl has expired, you will see error bytes returned to your consumer contract.

  1. Register the AutomationFunctionsConsumer contract for upkeep via the Chainlink Automation web app here: https://automation.chain.link/. This example uses a "Custom Logic" Automation.
    • Be sure to set the Gas limit for the performUpkeep function to a high enough value. The recommended value is 1,000,000.
    • Once created, ensure the Automation upkeep has sufficient funds. You can add funds, pause or cancel the upkeep in the web app.
    • Find further documentation for working with Chainlink Automation here: https://docs.chain.link/chainlink-automation/introduction

Once the contract is registered for upkeep, check the latest response or error with the commands npx hardhat functions-read --network network_name_here --contract 0x_contract_address.

  1. For debugging on your machine, use the command npx hardhat functions-check-upkeep --network network_name_here --contract contract_address_here to see if Automation needs to call performUpkeep. If this call returns false then the upkeep interval has not yet passed and performUpkeep will not execute. In order to test that performUpkeep will run correctly before registering the Automation upkeep, you can also trigger a request manually using the command npx hardhat functions-perform-upkeep --network network_name_here --contract contract_address_here

You can also attach a listener to a Subscription ID by updating the subId variable in /scripts/listen.js, and then running npm run listen --network your_network_name from the repo root in a new terminal so that it can keep listening as you develop. This script uses nodemon which restarts the script when you save files or when the listener returns a result.

Gas Spikes

When on-chain traffic is high, transaction gas prices can spike unexpectedly. This may decrease the accuracy of the estimated requests costs or cause transactions to fail. In order to mitigate these problems, ensure your Functions subscription balance has a sufficient buffer of two or more times the expected request cost in LINK. Additionally, you can manually set a hardcoded transaction gas price in the HardHat tooling by modifying the gasPrice parameter in the networks.js config file for a particular network.

Troubleshooting

  1. If you get strange (and scary large) error output in your terminal because a transaction failed, it is super helpful to use tenderly.co. Once you create an account, and a project look for "Transactions" in the tab list on the left, and past in your Transaction Hash. Tenderly will look across various networks for it. It will then show you the causes for the error especially if the contract has been verified. Here is a useful video on how to debug transactions with Tenderly:

    <iframe width="360" height="215" src="https://www.youtube.com/embed/90GN9Ut8LhU?si=iLhHegpG1Mq59qtJ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
  2. When running Chainlink Functions make sure your subscription ID has your FunctionsConsumer contract added as an authorized consumer. Also make sure that your subscription has enough LINK balance. You do this by calling npx hardhat functions-sub-info --network network_name_here --subid subscription_id_here to see your subscription details. If the Functions Router calculates that your subscription's balance is insufficient it will revert with a InsufficientBalance custom Solidity error.

  3. When running Chainlink Functions with Automation you also need to ensure the Chainlink Automation upkeeps are funded to run the automation calls. The fastest way to maintain your Automation LINK subscription balance is through the Chainlink Automation web app here: https://automation.chain.link/

  4. If you get a transaction failure when calling npx hardhat functions-request and its an out of gas error (you can tell from the block explorer or from Tenderly) then you may need to add the optional ---requestgaslimit flag with a value higher than than the default which is 1_500_000. For example: npx hardhat functions-request --requestgaslimit 1750000. Note that ./tasks/Functions-consumer/request.js already has some logic around this that applies to some networks that require higher gas.

  5. BASE Sepolia / Optimism Sepolia: if you see an error like ProviderError: transaction underpriced: tip needed 50, tip permitted 0 then wait a few seconds and re-try. This can happen due to network spikes. Also double check the ./networks.js file configs to make sure that gasPrice is set to 1000_000 as these networks can require higher request gas.

functions-hardhat-starter-kit's People

Contributors

007vasy avatar aelmanaa avatar bolekk avatar bsilagani avatar chudilka1 avatar codesandwich avatar dependabot[bot] avatar justinkaseman avatar khadni avatar kuphjr avatar momentmaker avatar virajpatva avatar zeuslawyer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

functions-hardhat-starter-kit's Issues

Simulation being executed ONLY AFTER user confirmed desire to continue with transaction

I used a mix of docs, readme and the following VDO (https://youtu.be/nKRZ1R2BC4Q?t=587) to familiarize myself with Chainlink functions.

While doing so I came across the following behavior, which appears to deviate from the behavior outlined in the docs/tutorial videos. I hope I am not wrong about this ;) :

EXPECTED BEHAVIOR:

  1. Executed npx hardhat functions-request --network polygonMumbai --contract [contractid] --subid [subid]
  2. Code contained in the function will be simulated and run locally
  3. CLI will provide a simulated result
  4. CLI will THEN estimate fees and asks user to confirm that they are willing to proceed

OBSERVED BEHAVIOR (see screenshot below):

  1. Executed npx hardhat functions-request --network polygonMumbai --contract [contractid] --subid [subid]
  2. CLI estimated fees and asks user to confirm that they are willing to proceed
  3. Only AFTER the user responded with YES will the function be simulated and run locally
  4. CLI will provide a simulated result

functions_observed

Other than that, its a great example, and a wonderful 'getting started' experience.

Error logs: Error encountered when calling fulfillRequest

My npx hardhat functions-simulate is failing due to the length of the response. If I remove ",Twitch Contrulla" from the below decoded string, the fulfillRequest function is successful. Is it something we should make even more obvious in the console logs for devs to understand whether it comes from gaslimit or response bytes limitation? @KuphJr

`Output from sandboxed source code
Output represented as a hex string: 0x53686173746120372c547769746368204a764d616669612c5477697463682057696c6c727a2c50575220776f727468756b2c54776974636820436f6e7472756c6c61
Decoded as a string: Shasta 7,Twitch JvMafia,Twitch Willrz,PWR worthuk,Twitch Contrulla

Error encountered when calling fulfillRequest in client contract.
Ensure the fulfillRequest function in the client contract is correct and the --gaslimit is sufficent.

Estimated transmission cost: 0.083559307848617261 LINK (This will vary based on gas price)
Base fee: 0.0 LINK
Total estimated cost: 0.083559307848617261 LINK`

No Concise Docs With Contract Examples

It is not clear what a basic implementation of a deployed contract looks like in the docs. The current docs require using Hardhat to setup. This goes against the standard in complementary documentation for subscriptions and VRF, things that will be frequently used with this service.

While Hardhat has its advantages in testing, having different styles of documentation makes it harder for developers to understand the macro picture of the underlying workings. It would be very nice to see a folder with compiled examples at the very least!

Error encountered when attempting to send request to DON gateway URL

I found an error using DON-hosted method but the User-hosted method is working for me while doing the request.

This is my error for the DON-hosted method:
{"jsonrpc":"2.0","id":"89015367","error":{"code":-32600,"message":"sender has insufficient balance: juels"}}

My EOA, the Contract Address and the Subscription, each everyone of them were funded more than 3 Links.

Unable to use `functions-sub-accept`

I create a sub from account 1 than created a transfer request and than changed private key in env to account 2 and tried the command but got the following error :

Error: This command requires a second wallet's private key to be made available in networks.js
    at SimpleTaskDefinition.action (/home/viraj/Documents/Blockchain/functions-hardhat-starter-kit/tasks/Functions-billing/accept.js:10:13)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at Environment._runTaskDefinition (/home/viraj/Documents/Blockchain/functions-hardhat-starter-kit/node_modules/hardhat/src/internal/core/runtime-environment.ts:333:14)
    at Environment.run (/home/viraj/Documents/Blockchain/functions-hardhat-starter-kit/node_modules/hardhat/src/internal/core/runtime-environment.ts:166:14)
    at main (/home/viraj/Documents/Blockchain/functions-hardhat-starter-kit/node_modules/hardhat/src/internal/cli/cli.ts:280:7)```

contract verification not going through

I have not been able to verify a contract since the process has changed and it is optional.
I tried using: --verify true or updated deploy.js to true by default or running npx hardhat verify
All contract creation transaction are pending (example)
Probably related to this PR @aelmanaa
Could come from the process.env.ETHERSCAN_API_KEY || process.env.POLYGONSCAN_API_KEY section

functions-sub-cancel not working on Polygon Mumbai

@KuphJr @justinkaseman

Subscription details are:

Subscription 23 owner: 0x208AA722Aca42399eaC5192EE778e4D42f4E5De3
Balance: 0.000000091 LINK
1 authorized consumer contract:
[ '0x4CA9b22A38dC98Af6195E595FE8200aEBf833A0C' ]

My contract address is verified.

When I try and run yhh functions-sub-cancel --network mumbai --subid 23 it works all the way to line 50 of cancel.js where we console out the number of confirmations we are waiting for.

And then it fails with the following output in console (and here is the polygonscan tx hash data).

I've seen CALL_EXCEPTION before where my address wasn't whitelisted, but that's not the case as I've run other commands. All the other commands work except for this.

Waiting 2 blocks for transaction 0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649 to be confirmed...

An unexpected error occurred:

Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (transactionHash="0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649", transaction={"hash":"0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649","type":2,"accessList":[],"blockHash":null,"blockNumber":null,"transactionIndex":null,"confirmations":0,"from":"0x208AA722Aca42399eaC5192EE778e4D42f4E5De3","gasPrice":{"type":"BigNumber","hex":"0x59682f12"},"maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x59682f00"},"maxFeePerGas":{"type":"BigNumber","hex":"0x59682f12"},"gasLimit":{"type":"BigNumber","hex":"0x1eddd8"},"to":"0xE7e4882E6cc98b4c20A5155ca83A18C85aaBfCe6","value":{"type":"BigNumber","hex":"0x00"},"nonce":59,"data":"0xd7ae1d300000000000000000000000000000000000000000000000000000000000000017000000000000000000000000208aa722aca42399eac5192ee778e4d42f4e5de3","r":"0xd58d55d4519718a39c48e5fc03251bd16968e99e786c294dd271a5f10ae63ac1","s":"0x3178dd6ed593ab840b293b98c967d05c63a16dc95fa0fe90c1f381f07e9983cf","v":0,"creates":null,"chainId":80001}, receipt={"to":"0xE7e4882E6cc98b4c20A5155ca83A18C85aaBfCe6","from":"0x208AA722Aca42399eaC5192EE778e4D42f4E5De3","contractAddress":null,"transactionIndex":2,"gasUsed":{"type":"BigNumber","hex":"0xa813"},"logsBloom":"0x00000000000000000000000000000000000000080000000000000010000000000000000000000020000000008000000000008000000000000000000000000000000000000000000000000000000000800000000002000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000000000001000000000000000000000000000000100000001000000000000000000000000000000000000000000000000000000000000000100000","blockHash":"0xafd003259728121c69a1d5bc12f7bb8b60659cbf88de4bb6c3f8bcf3640780fb","transactionHash":"0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649","logs":[{"transactionIndex":2,"blockNumber":31009926,"transactionHash":"0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649","address":"0x0000000000000000000000000000000000001010","topics":["0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63","0x0000000000000000000000000000000000000000000000000000000000001010","0x000000000000000000000000208aa722aca42399eac5192ee778e4d42f4e5de3","0x000000000000000000000000f903ba9e006193c1527bfbe65fe2123704ea3f99"],"data":"0x00000000000000000000000000000000000000000000000000003ab301937d0000000000000000000000000000000000000000000000000002420d11f14a39e80000000000000000000000000000000000000000000009d98d2832e49b77de620000000000000000000000000000000000000000000000000241d25eefb6bce80000000000000000000000000000000000000000000009d98d286d979d0b5b62","logIndex":6,"blockHash":"0xafd003259728121c69a1d5bc12f7bb8b60659cbf88de4bb6c3f8bcf3640780fb"}],"blockNumber":31009926,"confirmations":3,"cumulativeGasUsed":{"type":"BigNumber","hex":"0x05e7d8"},"effectiveGasPrice":{"type":"BigNumber","hex":"0x59682f0f"},"status":0,"type":2,"byzantium":true}, code=CALL_EXCEPTION, version=providers/5.7.2)
    at Logger.makeError (/Users/zubinpratap/Documents/code/ocr-on-demand/demor2-billing-tooling/node_modules/@ethersproject/logger/src.ts/index.ts:269:28)
    at Logger.throwError (/Users/zubinpratap/Documents/code/ocr-on-demand/demor2-billing-tooling/node_modules/@ethersproject/logger/src.ts/index.ts:281:20)
    at EthersProviderWrapper.<anonymous> (/Users/zubinpratap/Documents/code/ocr-on-demand/demor2-billing-tooling/node_modules/@ethersproject/providers/src.ts/base-provider.ts:1549:24)
    at step (/Users/zubinpratap/Documents/code/ocr-on-demand/demor2-billing-tooling/node_modules/@ethersproject/providers/lib/base-provider.js:48:23)
    at Object.next (/Users/zubinpratap/Documents/code/ocr-on-demand/demor2-billing-tooling/node_modules/@ethersproject/providers/lib/base-provider.js:29:53)
    at fulfilled (/Users/zubinpratap/Documents/code/ocr-on-demand/demor2-billing-tooling/node_modules/@ethersproject/providers/lib/base-provider.js:20:58) {
  reason: 'transaction failed',
  code: 'CALL_EXCEPTION',
  transactionHash: '0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649',
  transaction: {
    hash: '0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649',
    type: 2,
    accessList: [],
    blockHash: null,
    blockNumber: null,
    transactionIndex: null,
    confirmations: 0,
    from: '0x208AA722Aca42399eaC5192EE778e4D42f4E5De3',
    gasPrice: BigNumber { value: "1500000018" },
    maxPriorityFeePerGas: BigNumber { value: "1500000000" },
    maxFeePerGas: BigNumber { value: "1500000018" },
    gasLimit: BigNumber { value: "2022872" },
    to: '0xE7e4882E6cc98b4c20A5155ca83A18C85aaBfCe6',
    value: BigNumber { value: "0" },
    nonce: 59,
    data: '0xd7ae1d300000000000000000000000000000000000000000000000000000000000000017000000000000000000000000208aa722aca42399eac5192ee778e4d42f4e5de3',
    r: '0xd58d55d4519718a39c48e5fc03251bd16968e99e786c294dd271a5f10ae63ac1',
    s: '0x3178dd6ed593ab840b293b98c967d05c63a16dc95fa0fe90c1f381f07e9983cf',
    v: 0,
    creates: null,
    chainId: 80001,
    wait: [Function (anonymous)]
  },
  receipt: {
    to: '0xE7e4882E6cc98b4c20A5155ca83A18C85aaBfCe6',
    from: '0x208AA722Aca42399eaC5192EE778e4D42f4E5De3',
    contractAddress: null,
    transactionIndex: 2,
    gasUsed: BigNumber { value: "43027" },
    logsBloom: '0x00000000000000000000000000000000000000080000000000000010000000000000000000000020000000008000000000008000000000000000000000000000000000000000000000000000000000800000000002000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000000000001000000000000000000000000000000100000001000000000000000000000000000000000000000000000000000000000000000100000',
    blockHash: '0xafd003259728121c69a1d5bc12f7bb8b60659cbf88de4bb6c3f8bcf3640780fb',
    transactionHash: '0x8ba5c009dc40d4f51b5347c7b844deb74be7ed8f622d9ee0fb9942b107a95649',
    logs: [ [Object] ],
    blockNumber: 31009926,
    confirmations: 3,
    cumulativeGasUsed: BigNumber { value: "387032" },
    effectiveGasPrice: BigNumber { value: "1500000015" },
    status: 0,
    type: 2,
    byzantium: true
  }
}
error Command failed with exit code 1.

never ending listen for fulfillment in functions-request

I'm using netowrk localFunctionsTestnet and when trying to run a local functions-request the following is happening:

➜  npx hardhat functions-request --network localFunctionsTestnet --contract 0xef9fDC41236486FD497b0811FA197F8195bb1cB4 --subid 1 --simulate true

secp256k1 unavailable, reverting to browser version

Response returned by script during local simulation: 3

Local simulation of source code completed...
If the request's callback uses all 100,000 gas, this request will charge the subscription an estimated 0.37846 LINK

Continue? Enter (y) Yes / (n) No
y
⣾ Functions request has been initiated in transaction 0xc46e62b3018891d6e9ac902be6b079c54cd24b246bf35526011a3b06b5a42eb4 with request ID 0x80bd3df61d97ffc35adf369dce738a86027f69df4ef61b1bcca8c042247f4698. Note the request ID may change if a re-org occurs, but the transaction hash will remain constant.
Waiting for fulfillment from the Decentralized Oracle Network...
^C⏎                                                                                                                                                            

That keeps waiting, but never finishes. Although, when I check the on-chain resposne, it did happen and update the value in the contract:

➜  npx hardhat functions-read --network localFunctionsTestnet --contract 0xef9fDC41236486FD497b0811FA197F8195bb1cB4                           05/24/24 - 10:11 
secp256k1 unavailable, reverting to browser version
Reading data from Functions consumer contract 0xef9fDC41236486FD497b0811FA197F8195bb1cB4 on network localFunctionsTestnet

On-chain response represented as a hex string: 0x0000000000000000000000000000000000000000000000000000000000000003
3

It is possible to reproduce this problem with the steps in the readme In this folder repo's "fork" of this starter kit:
https://github.com/propytech-dao/chainlink-hackaton/tree/main/functions-hardhat-starter-kit#readme

functions-sub-add not working on Goerli

Trying to add a newly deployed contract to an existing billing subid account the same wallet (deployer) owns.
I assume that this function has been disabled by default and the .ignore file has to be updated

Error:
Found & ignored ./build/artifacts ; is listed in .gitignore
Found & ignored ./build/cache ; is listed in .gitignore

Some responses are too big to be stored in `latestResponse`

Some API responses & function computations are larger than 32 bytes so the entire response can't be saved in latestResponse. Most notably ChatGPT due to the way it generates tokens (which I assume a lot of people will be trying out).

In those cases it will throw this error: Error message returned to client contract: "returned Buffer >256 bytes"

function simulation error

hi,

I am trying to run
npx hardhat function-simulate on an unchanged repo
and I am getting:

Duplicate definition of Transfer (Transfer(address,address,uint256,bytes), Transfer(address,address,uint256))
Error: Transaction reverted: function call to a non-contract account
    at FunctionsBillingRegistry.getFeedData (contracts/dev/functions/FunctionsBillingRegistry.sol:517)
    at FunctionsBillingRegistry.estimateCost (contracts/dev/functions/FunctionsBillingRegistry.sol:289)
    at FunctionsBillingRegistry.startBilling (contracts/dev/functions/FunctionsBillingRegistry.sol:334)
    at FunctionsOracle.sendRequest (contracts/dev/functions/FunctionsOracle.sol:172)
    at FunctionsConsumer.sendRequest (contracts/dev/functions/FunctionsClient.sol:63)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at HardhatNode._mineBlockWithPendingTxs (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1802:23)
    at HardhatNode.mineBlock (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:491:16)
    at EthModule._sendTransactionAndReturnHash (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1522:18)
    at HardhatNetworkProvider.request (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:118:18)
    at EthersProviderWrapper.send (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)

tested on:

  • Mac M1
    • node: 18.14.0
    • npm: 9.3.1
    • hardhat: 2.12.0
  • Ubuntu (22.04.1)
    • node: 18.14.0
    • npm: 9.3.1
    • hardhat: 2.12.0

I could deploy a contract to sepolia

let me know if I am just dumb or I am just missing something

using keccak256 hash function

In the documentation, it says that developers can require built-in crypto module. Does this crypto module refer to the encryptSecrets script in the sandbox folder? If not, does this module include keccak256 hash function? If it does, how can we import this hash function?

.chainlink_functions folder generated

Hello @justinkaseman,

I noticed that when testing the feat/remove-inline-secrets branch, a new folder named .chainlink_functions appears. Shouldn't we add this folder to the .gitignore file?

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .chainlink_functions/

npm package tree has high and crit vulnerabilities

npm install yields

16 vulnerabilities (7 moderate, 5 high, 4 critical)

forcing a patch introduces breaking changes and more vulnerabilities in the audit tree

Is there an existing feature branch getting these to 0?

-Brett-

Verification is not generic enough

https://github.com/smartcontractkit/ocr2dr-hardhat-starter-kit/blob/d995299bd0c0da492629872995f1a622a4bb7d8c/tasks/Functions-client/deploy.js#L25

Hi @justinkaseman @KuphJr

this line is not generic enough. Each time that a new network is supported, the line will have to be modified. I'd propose something like this:

  • Add an optional task parameter to ask the user if they want to verify their contract (e.g.: --verify true)
  • Rely on the standard verify plugin mechanism. The verify task would fail if the user didn't provide the right API_KEY. Because you catch the error, you will display the reason for verification failure at the end

error while running npx functions-request

hi,

I can deploy a contract, and I created a subcription easliy, but when I try to run:
npx hardhat functions-request --network sepolia --contract 0x1Ae7F4caf34BbBaa13CFc7Ec5f835506fc807f0b --subid 57
then I get:

❯ npx hardhat functions-request --network sepolia --contract 0x1Ae7F4caf34BbBaa13CFc7Ec5f835506fc807f0b --subid 57
secp256k1 unavailable, reverting to browser version
Simulating Functions request locally...

__Console log messages from sandboxed code__

__Output from sandboxed source code__
Output represented as a hex string: 0x00000000000000000000000000000000000000000000000000000000000f50ed
Decoded as a uint256: 1003757


If all 100000 callback gas is used, this request is estimated to cost 0.426465500634489687 LINK
Continue? (y) Yes / (n) No
y

Requesting new data for FunctionsConsumer contract 0x1Ae7F4caf34BbBaa13CFc7Ec5f835506fc807f0b on network sepolia
Waiting 2 blocks for transaction 0x84f976729da85d554547dcc51222d672beba615cb95e1110e5112ab84e785307 to be confirmed...

/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@ethersproject/logger/src.ts/index.ts:269
        const error: any = new Error(message);
                           ^
Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (transactionHash="0x84f976729da85d554547dcc51222d672beba615cb95e1110e5112ab84e785307", transaction={"hash":"0x84f976729da85d554547dcc51222d672beba615cb95e1110e5112ab84e785307","type":0,"accessList":null,"blockHash":null,"blockNumber":null,"transactionIndex":null,"confirmations":0,"from":"0x4618B0c5A1d6957F0b9620A4504b08Ed31b22736","gasPrice":{"type":"BigNumber","hex":"0x0b44dd6400"},"gasLimit":{"type":"BigNumber","hex":"0x16e360"},"to":"0x1Ae7F4caf34BbBaa13CFc7Ec5f835506fc807f0b","value":{"type":"BigNumber","hex":"0x00"},"nonce":8,"data":"0xd22b224a00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000004622f2f2054686973206578616d706c652073686f777320686f7720746f2063616c63756c617465206120636f6e74696e756f75736c7920636f6d706f756e64696e6720696e746572657374656420726174652e0a2f2f20546869732063616c63756c6174696f6e20776f756c642072657175697265207369676e69666963616e74206f6e2d636861696e206761732c20627574206973206561737920666f72206120646563656e7472616c697a6564206f7261636c65206e6574776f726b2e0a0a2f2f20417267756d656e74732063616e2062652070726f7669646564207768656e2061207265717565737420697320696e697461746564206f6e2d636861696e20616e64207573656420696e20746865207265717565737420736f7572636520636f64652061732073686f776e2062656c6f770a636f6e7374207072696e636970616c416d6f756e74203d207061727365496e7428617267735b345d290a636f6e73742041505954696d6573313030203d207061727365496e7428617267735b355d290a636f6e7374204150594173446563696d616c50657263656e74616765203d2041505954696d6573313030202f20313030202f203130300a0a636f6e73742074696d65496e5965617273203d2031202f203132202f2f20726570726573656e74732031206d6f6e74680a636f6e73742065756c6572734e756d626572203d20322e373138330a0a2f2f20436f6e74696e756f75736c792d636f6d706f756e64696e6720696e74657265737420666f726d756c613a2041203d2050655e287274290a636f6e737420746f74616c416d6f756e744166746572496e746572657374203d207072696e636970616c416d6f756e74202a2065756c6572734e756d626572202a2a20284150594173446563696d616c50657263656e74616765202a2074696d65496e5965617273290a0a2f2f2054686520736f7572636520636f6465204d5553542072657475726e206120427566666572206f722074686520726571756573742077696c6c2072657475726e20616e206572726f72206d6573736167650a2f2f20557365206f6e65206f662074686520666f6c6c6f77696e672066756e6374696f6e7320746f20636f6e7665727420746f20612042756666657220726570726573656e74696e672074686520726573706f6e73652062797465732074686174206172652072657475726e656420746f2074686520636c69656e7420736d61727420636f6e74726163743a0a2f2f202d2046756e6374696f6e732e656e636f646555696e743235360a2f2f202d2046756e6374696f6e732e656e636f6465496e743235360a2f2f202d2046756e6374696f6e732e656e636f6465537472696e670a2f2f204f722072657475726e206120637573746f6d2042756666657220666f72206120637573746f6d206279746520656e636f64696e670a72657475726e2046756e6374696f6e732e656e636f646555696e74323536284d6174682e726f756e6428746f74616c416d6f756e744166746572496e74657265737429290a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111432a9d448855c59279131ec8bbcf842e02b16a4e5c4c2ceaa034cf952623f76ebc3bf93fc03c53fc857b68c21a93dee6f5782e21bf8823081fe0316db94dc0eadadfddcf41178016d930bd93fad5052bd8753b20f7e0876d5bc02968affd6f2f5780989ebf66a84bd4d3a46a88892400576b1583b406e914d2be8af662dbe34447bd9e899bd98538070c8191afd76aeae4c3d48b411274397347a3d44a7af76e8c1a42b7f07a916ed073bc9e652af68222b4565d474cb43eb7bc13d8ddd9c2c565bc23169ca87be875c6ede1fc331243cb49644a6c0551c5deb3415540b49fd4650d52c35547545d746c0859904f9bf67af6bcfbeee4279c28a38afa013065d27c31853cb3418d8659eb778eb414778e2f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000131000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007626974636f696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6274632d626974636f696e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000362746300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007313030303030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033435300000000000000000000000000000000000000000000000000000000000","r":"0xb2c49b4ec653151dbc272b02a8158076bca45c8f1efa37631bf65a4f6c83706c","s":"0x22689e70531ee85988f198026af642709553831a1366a9f44f155149626f5c9c","v":22310258,"creates":null,"chainId":11155111}, receipt={"to":"0x1Ae7F4caf34BbBaa13CFc7Ec5f835506fc807f0b","from":"0x4618B0c5A1d6957F0b9620A4504b08Ed31b22736","contractAddress":null,"transactionIndex":1,"gasUsed":{"type":"BigNumber","hex":"0x029fde"},"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","blockHash":"0x597ac7823dccb6b69c7fb18482b12b048fc6d3c43c930f36500d31e80d8060c0","transactionHash":"0x84f976729da85d554547dcc51222d672beba615cb95e1110e5112ab84e785307","logs":[],"blockNumber":3024050,"confirmations":2,"cumulativeGasUsed":{"type":"BigNumber","hex":"0x02f9e6"},"effectiveGasPrice":{"type":"BigNumber","hex":"0x0b44dd6400"},"status":0,"type":0,"byzantium":true}, code=CALL_EXCEPTION, version=providers/5.7.2)
    at Logger.makeError (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@ethersproject/logger/src.ts/index.ts:269:28)
    at Logger.throwError (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@ethersproject/logger/src.ts/index.ts:281:20)
    at EthersProviderWrapper.<anonymous> (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@ethersproject/providers/src.ts/base-provider.ts:1549:24)
    at step (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@ethersproject/providers/lib/base-provider.js:48:23)
    at Object.next (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@ethersproject/providers/lib/base-provider.js:29:53)
    at fulfilled (/Users/benvass/Projects/functions-hardhat-starter-kit/node_modules/@ethersproject/providers/lib/base-provider.js:20:58)

Need encode multiple value

We need implement this function

FunctionsModule.encode(["uint256", "string", "int256"], [1, "test", -1]);

Because many production app needs multiple value response. it able to decode multiple value like this

function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {
abi.decode(response, (uint256, string, int256));
}

AutomatedFunctionsConsumer: Gist not removed when you update a request

I want to report an edge case with the tooling. Test the following for an AutomatedFunctionsConsumer contract. Make sure that your config file uses secrets:

  1. In your editor, open the store of your contract. It should be in ./chainlink_functions/80001-polygonMumbai/automatedConsumer/<your-contract-address>.json

  2. You can scroll down to the secretsURLs key. You should see a gist (Example: https://gist.github.com/aelmanaa/c679709234e213dfa2ca74097d0b42a3/raw)

  3. Run npx hardhat functions-set-auto-request to update the request object. At this point, the tooling generates a new gist and tries to delete previous gists.

Successfully created encrypted secrets Gist: https://gist.github.com/aelmanaa/358e6987764e254b0a5689910dce7b7b
Be sure to delete the Gist https://gist.github.com/aelmanaa/358e6987764e254b0a5689910dce7b7b once encrypted secrets are no longer in use!

Setting Functions request

Waiting 2 block for transaction 0xa72356e0d816774f0597bffcffb8296e8cea74c4725e603d3771d116381cb889 to be confirmed...
Attempting to clean up previous GitHub Gist secrets

In my case, a new gist https://gist.github.com/aelmanaa/358e6987764e254b0a5689910dce7b7b, has been created. However, the old one, https://gist.github.com/aelmanaa/c679709234e213dfa2ca74097d0b42a3/raw has not been deleted. (I had to delete it manually).

IMO, there are 2 UX issues:

  1. Don't display this warning Attempting to clean up previous GitHub Gist secrets If you are not going to remove the gist secrets
  2. The previous gist is cleared from the store without any warning. Either warn the users so that they delete the gist manually OR delete the previous gist

Issue with Integrating localFunctionsTestnet and Hardhat's loadFixture Utility

Description:
Hello, and thank you for providing this excellent boilerplate for working with Chainlink Functions.

I am currently developing a Smart Contract and utilizing your provided localFunctionsTestnet for testing. However, I've encountered an issue related to testing environments. Specifically, the need to manually run localFunctionsTestnet prevents me from taking full advantage of Hardhat's loadFixture utility, which is instrumental for snapshotting test states.

Problem:
The localFunctionsTestnet, as part of the functions-toolkit, uses Ganache under the hood. This setup conflicts with Hardhat's default behavior, particularly with the loadFixture utility, which relies on Hardhat's in-memory network for snapshotting and reverting state between tests. The result is an inability to efficiently manage test state, leading to more complex and time-consuming test setups.

Expected Behavior:
Ideally, I would like to seamlessly integrate the localFunctionsTestnet with Hardhat's testing environment, enabling me to use loadFixture for efficient test state management. This integration would greatly enhance the development workflow and testing efficiency.

Steps to Reproduce:

  1. Set up a Smart Contract project using the Chainlink Functions boilerplate.
  2. Implement unit tests using Hardhat's testing framework.
  3. Attempt to use Hardhat's loadFixture utility while localFunctionsTestnet is running.

Possible Solutions:
I'm unsure of the best way to resolve this issue but have considered a few options:

  1. Adapting localFunctionsTestnet for Compatibility: Modify localFunctionsTestnet to work seamlessly with Hardhat's in-memory network, allowing us to use loadFixture effectively.
  2. Guidance on Managing Test States: Provide instructions or best practices for handling test states when using localFunctionsTestnet alongside Hardhat.
  3. Script to Replicate localFunctionsTestnet Setup in Hardhat: Develop a script to configure Hardhat's test environment similar to localFunctionsTestnet, ensuring consistency across testing platforms.

Thank you for your attention to this issue. Any guidance or updates to improve this integration would be greatly appreciated!

Need to wait X blocks before verifying

If you verify before polygonscan/etherscan has a chance to process the transaction, you'll run into an error where it can't verify the code.

These lines need to have a wait command for 3 number of blocks (I've found 6 to be pretty good. 4 is probably fine too. 2 is too low. )

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.