Oracle Integration

DegenPrime uses RedStone oracles to provide real-time price data. Solvency-sensitive transactions must include RedStone price data wrapped in the calldata.

How It Works

Unlike push-based oracles (Chainlink), RedStone uses a pull-based model. Price data is fetched off-chain and appended to the transaction calldata. The on-chain contract verifies the data signatures before using the prices for solvency calculations.

Provider

RedStone

Data Feed

redstone-arbitrum-prod

Required Signers

3 of 5

When Is Wrapping Required?

Any transaction that triggers a solvency check must include RedStone price data. These operations include:

OperationRequires WrappingWhy
borrow()YesChecks solvency after borrowing
paraSwap()YesChecks solvency after swap
fulfillWithdrawalIntent()YesChecks solvency after withdrawal
liquidateLoan()YesVerifies loan is insolvent
addLiquidityAerodrome()YesChecks solvency after LP change
fund()NoOnly adds collateral
repay()NoOnly reduces debt

Using WrapperBuilder

The @redstone-finance/evm-connector package provides the WrapperBuilder that automatically fetches current prices and appends them to your contract calls.

typescript
import { WrapperBuilder } from "@redstone-finance/evm-connector";
import { ethers } from "ethers";

// 1. Create an ethers contract instance
const provider = new ethers.JsonRpcProvider("https://mainnet.base.org");
const signer = new ethers.Wallet(privateKey, provider);
const contract = new ethers.Contract(loanAddress, smartLoanAbi, signer);

// 2. Wrap it with RedStone
const wrappedContract = WrapperBuilder
  .wrap(contract)
  .usingDataService({
    dataServiceId: "redstone-arbitrum-prod",
    uniqueSignersCount: 3,
    dataFeeds: ["ETH", "USDC", "BTC", "AERO"],
  });

// 3. Call methods normally -- prices are injected automatically
const tx = await wrappedContract.borrow(tokenId, amount);
await tx.wait();

Using with Viem

If you are using viem instead of ethers, you will need to use the ethers WrapperBuilder adapter or manually construct the RedStone calldata.

typescript
import { DataServiceWrapper } from "@redstone-finance/evm-connector";

// For viem users: construct RedStone calldata manually
const wrapper = new DataServiceWrapper({
  dataServiceId: "redstone-arbitrum-prod",
  dataFeeds: ["ETH", "USDC"],
  uniqueSignersCount: 3,
});

// Get the unsigned metadata (price data + signatures)
const redstonePayload = await wrapper.getRedstonePayloadForManualUsage(
  contract // ethers contract instance for ABI encoding
);

// Append the redstone payload to your viem calldata
const originalCalldata = encodeFunctionData({
  abi: borrowingFacetAbi,
  functionName: "borrow",
  args: [tokenId, amount],
});

const wrappedCalldata = originalCalldata + redstonePayload;

// Send via viem
await walletClient.sendTransaction({
  to: loanAddress,
  data: wrappedCalldata,
});

Troubleshooting

"CalldataMustHaveValidPayload" error

The RedStone data is missing or malformed. Ensure you are using WrapperBuilder to wrap the contract before calling methods.

"SignerNotAuthorised" error

The price data signatures are not from authorized RedStone signers. Use redstone-arbitrum-prod as the data service ID.

"TimestampIsNotValid" error

The price data is too old. RedStone data must be recent (within a few minutes). This can happen if your request is delayed.