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:
| Operation | Requires Wrapping | Why |
|---|---|---|
| borrow() | Yes | Checks solvency after borrowing |
| paraSwap() | Yes | Checks solvency after swap |
| fulfillWithdrawalIntent() | Yes | Checks solvency after withdrawal |
| liquidateLoan() | Yes | Verifies loan is insolvent |
| addLiquidityAerodrome() | Yes | Checks solvency after LP change |
| fund() | No | Only adds collateral |
| repay() | No | Only 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.
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.
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.