npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@chaos-labs/chainlink-hardhat-plugin

v0.0.6

Published

Hardhat plugin for configuring Chainlink price feed return values when forking mainnet.

Downloads

7

Readme

Chaos Labs - Chainlink Collab

TLDR

  • This repository hosts a hardhat plugin for configuring Chainlink Oracle prices in a local hardhat mainnet fork testing environment.
  • The plugin fetches all Mainnet Chainlink Oracle addresses when invoked and makes them accessible for price modification.
  • The only thing the user should supply is the token pair ticker or a price config. Let's explore the different options.

Set Prices Explicity with the following init config

await chainlinkConfig.initChainlinkPriceFeedConfig("ETH/USD", "Mainnet");
await chainlinkConfig.initChainlinkPriceFeedConfig("AAVE/USD", "Mainnet");
await chainlinkConfig.initChainlinkPriceFeedConfig("ETH/BTC", "Mainnet");

More on this here!

Set Prices trends with the following config

https://user-images.githubusercontent.com/8246234/151700339-b4ca4706-697d-40b9-be7d-f603cd7be6c5.mov

const config = {
  priceDelta: 10,
  priceFunction: "volatile",
  initialPrice: 0,
};
await chainlinkConfig.initChainlinkPriceFeedConfig(ticker, "Mainnet", config);

Grab a config via the Chainlink portal!

More on this here!

Why is Mocking Oracle values useful in testing?

Oracle values trigger internal state changes in web3 applications. Currently, when forking mainnent, oracle returns values are constant. This is because the Chainlink protocol only writes updated values to mainnet or public testnets. We want the ability to mock return values easily, so we can test how our contracts / applications react to different types of external data, hence this tool. Below, we provide some specific use cases for mocking oracle return values.

For a full deep dive to the project architecture please visit the Chaos Labs blog.

Use Cases

DeFi protocols and applications are at high risk due to volatile market conditions and a myriad of security vectors. Mocking Chainlink Oracle return values in a controlled, siloed testing environment allows us to address 2 common vectors.

Volatile Market Conditions

Volatility is a DeFi constant and is something that all protocols and applications should test for thoroughly. Internal application and protocol state is often a direct result of Oracle returns values. To further illustrate this let's use an example.

Imagine a lending protocol (Maker, AAVE, Benqi, Spectral.finance, etc..) that accepts Ethereum as collateral against stablecoin loans. What happens on a day like Black Thursday, when Ethereum prices cascade negatively to the tune of ~70% in a 48 hour time frame? Well, a lot of things happen 🤦.

Black Thursday Img

One critical aspect of responding to market volatiltiy is protocol keepers triggering liquidations and thus ensuring protocol solvency.

With the ability to control Oracle return values, simulating such scenarios in your local development environment is possible.

Oracle Manipulation

Oracle manipulation is an additional attack vector. With this method, malicious actors research data sources that various oracle consume as sources of truth. When actors possess the ability to manipulate the underlying data source they trigger downstream effects, manifesting in altered Oracle return values. As a result of manipulated data, actors and contracts can trigger various unwanted behaviours such as modified permissions, transaction execution, emergency pausing / shutdown and more.

With the ability to manipulate Chainlink Oracle return values, simulating such scenarios in your local development environment is possible.

Prerequisites

  • We're going to need an instance of a hardhat mainnet fork running in a separate terminal window. For a quickstart, follow the installation steps in our Chaos Labs demo repo.
  • We assume you have npm installed, if not go to https://nodejs.org/en/download/ and follow the instructions.

Installation

Step 1

npm install ChaosLabsInc/chainlink-hardhat-plugin

Step 2

Import the plugin in your hardhat.config.js:

require("@chaos-labs/chainlink-hardhat-plugin");

Or if you are using TypeScript, in your hardhat.config.ts:

import "@chaos-labs/chainlink-hardhat-plugin";

Usage - Set Prices Explicity

In this example we will explicitly set the return value of a Chainlink price feed.

const chainlinkConfig = new hre.ChainlinkPriceFeedConfig(this.hre);
// Here we set the plugin to work with ETH/USD pair on Mainnet:
await chainlinkConfig.initChainlinkPriceFeedConfig("ETH/USD", "Mainnet");
// Now we query the price, this is to allow better decision making in setting up the mocked price:
const prevPrice = await chainlinkConfig.getPrice("ETH/USD"); // original price at time of mainnet fork
// We mock the price of the return value fo the token to 555 instead of the original price:
await chainlinkConfig.setPrice("ETH/USD", 555);
const nextPrice = await chainlinkConfig.getPrice("ETH/USD"); // 555

Usage - Set Prices via Configuration

Grab a config via the Chainlink portal!

Some test cases require testing trends in pricing. For example, we may want to test examples in which TokenA is decreasing in a monotonic fashion. For this use case we can grab a Chainlink Configuration object and pass it to the initChainlinkPriceFeedConfig initializer.

const chainlinkConfig = new ChainlinkPriceFeedConfig(this.hre);
const config = {
  priceDelta: 10,
  priceFunction: "volatile",
  initialPrice: 0,
};
await chainlinkConfig.initChainlinkPriceFeedConfig(ticker, "Mainnet", config);
let price = await chainlinkConfig.getPrice(ticker); // 0
await chainlinkConfig.nextPrice(ticker);
price = await chainlinkConfig.getPrice(ticker); // -10
await chainlinkConfig.nextPrice(ticker);
price = await chainlinkConfig.getPrice(ticker); // 20

Copy Config To Clipboard

After selecting a math function to describe the direction of oracle change, please click on the Export Button. This will pop up a dialog. Click the "Copy" button to copy the config to your clipboard or download it as a json file with the "Download" button.

Paste Config into Hardhat Script

Now that our config has been copied to our keyboard we can copy it into our hardhat script. You can set the paste as the value of the config variable above or paste it directly into the init method:

await chainlinkConfig.initChainlinkPriceFeedConfig(ticker, "Mainnet", {
  priceDelta: 10,
  priceFunction: "volatile",
  initialPrice: 0,
});

as the third parameter - replacing the config variable with the object literal.

How Do Prices Behave As We Query Next Price?

The following image shows the price behavior between subsequent calls to nextPrice(ticker)

image

Run Tests

  1. Restart the mainnet fork for a fresh state.

  2. Run tests with the following command:

npm run build && npm run test

Tests output