Skip to content

Commit

Permalink
refactor: cleanup
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Maldonado <pablo@umaproject.org>
  • Loading branch information
md0x committed May 16, 2024
1 parent 7ab11ab commit 26c33a1
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 119 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ jobs:
with:
version: "nightly-de33b6af53005037b463318d2628b5cfcaf39916"

- name: "Navigate to redstone and install dependencies"
run: |
cd redstone
yarn install
- name: "Show the Foundry config"
run: "forge config"

Expand Down
3 changes: 2 additions & 1 deletion getRedstonePayload.log.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
An error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableYou have to provide at least one dataFeedAn error occurred: provided input is not valid bytes value
An error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableAn error occurred: this.signedDataPackages.map is not a function or its return value is not iterableYou have to provide at least one dataFeedAn error occurred: provided input is not valid bytes valueAn error occurred: Request failed {"reqParams":{"dataServiceId":"redstone-primary-prod","uniqueSignersCount":3,"dataFeeds":["BTC:120:8"],"urls":["https://oracle-gateway-1.a.redstone.finance"]}}, Original error: AggregateError: , errors: Error: Requested data feed id is not included in response: BTC:120:8
at parseAndValidateDataPackagesResponse (/Users/salvadorpablomaldonadoturci/ghq/github.com/UMAprotocol/oval-contracts/redsto...
76 changes: 25 additions & 51 deletions redstone/getRedstonePayload.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
const { appendFileSync } = require("fs");
const {
DataPackage,
NumericDataPoint,
RedstonePayload,
} = require("@redstone-finance/protocol");
const { RedstonePayload } = require("@redstone-finance/protocol");
const web3 = require("web3");
const sdk = require("@redstone-finance/sdk");
const args = process.argv.slice(2);
Expand All @@ -20,69 +16,47 @@ const parsePrice = (value) => {
return Number(bigNumberPrice);
};

const main = async () => {
if (args.length === 0) {
exit(1, "You have to provide at least on dataFeed");
const pickMedian = (arr) => {
if (arr.length === 0) {
throw new Error("Cannot pick median of empty array");
}

const dataFeeds = args[0].split(",");

if (dataFeeds.length === 0) {
exit(2, "You have to provide at least on dataFeed");
arr.sort((a, b) => a - b);
const middleIndex = Math.floor(arr.length / 2);
if (arr.length % 2 === 0) {
return (arr[middleIndex - 1] + arr[middleIndex]) / 2;
} else {
return arr[middleIndex];
}
};

const timestampMilliseconds = Date.now();

const PRIVATE_KEY_1 =
"0x548e7c2fae09cc353ffe54ed40609d88a99fab24acfc81bfbf5cd9c11741643d";

const dataPoints = dataFeeds.map((arg) => {
const [dataFeedId, value, decimals] = arg.split(":");

if (!dataFeedId || !value || !decimals) {
exit(
3,
"Input should have format: dataFeedId:value:decimals (example: BTC:120:8)"
);
}

return new NumericDataPoint({
dataFeedId,
value: parseInt(value),
decimals: parseInt(decimals),
});
});

// Prepare unsigned data package
const dataPackage = new DataPackage(dataPoints, timestampMilliseconds);
const main = async () => {
if (args.length === 0) {
exit(1, "You have to provide a data Feed");
}

// Prepare signed data packages
const signedDataPackages = [dataPackage.sign(PRIVATE_KEY_1)];
const dataFeed = args[0];

const getLatestSignedPrice = await sdk.requestDataPackages({
dataServiceId: "redstone-primary-prod",
uniqueSignersCount: 3,
dataFeeds: ["BTC"],
dataFeeds: [dataFeed],
urls: ["https://oracle-gateway-1.a.redstone.finance"],
});

// const payload = RedstonePayload.prepare(signedDataPackages, "");
const payload = RedstonePayload.prepare(getLatestSignedPrice["BTC"], "");
const prices = getLatestSignedPrice[dataFeed].map((dataPackage) =>
parsePrice(dataPackage.dataPackage.dataPoints[0].value)
);

const medianPrice = pickMedian(prices);

// process.stdout.write("0x" + payload)
const payload = RedstonePayload.prepare(getLatestSignedPrice[dataFeed], "");

const timestampMS =
getLatestSignedPrice["BTC"][0].dataPackage.timestampMilliseconds;
getLatestSignedPrice[dataFeed][0].dataPackage.timestampMilliseconds;

const encodedData = web3.eth.abi.encodeParameters(
["bytes", "uint256", "uint256"],
[
"0x" + payload,
timestampMS,
parsePrice(
getLatestSignedPrice["BTC"][0].dataPackage.dataPoints[0].value
),
]
["0x" + payload, timestampMS, medianPrice]
);

process.stdout.write(encodedData);
Expand Down
113 changes: 46 additions & 67 deletions test/unit/RedStoneOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {DecimalLib} from "../../src/adapters/lib/DecimalLib.sol";
import {IAggregatorV3Source} from "../../src/interfaces/chainlink/IAggregatorV3Source.sol";
import {RedstonePriceFeedWithRounds} from "../../src/oracles/RedstonePriceFeedWithRounds.sol";

import "forge-std/console.sol";
import {IAggregatorV3Source} from "../../src/interfaces/chainlink/IAggregatorV3Source.sol";

import {TestedSourceAdapter} from "../fork/adapters/ChainlinkSourceAdapter.sol";

contract MockRedstonePayload is CommonTest {
function getRedstonePayload(
Expand All @@ -27,39 +29,25 @@ contract MockRedstonePayload is CommonTest {
}
}

contract RedstoneOracleAdapterTest is
CommonTest,
MockRedstonePayload,
RedstoneConsumerNumericBase
{
contract RedstoneOracleAdapterTest is CommonTest, MockRedstonePayload {
RedstonePriceFeedWithRounds redstoneOracle;
TestedSourceAdapter sourceAdapter;

function setUp() public {
redstoneOracle = new RedstonePriceFeedWithRounds(bytes32("BTC"));
}

function testPushPrice() public {
bytes memory data = getRedstonePayload("BTC:120:8");

(bytes memory redstonePayload, uint256 timestampMilliseconds, uint256 updatePrice) = abi
.decode(data, (bytes, uint256,uint256));

bytes memory encodedFunctionNumericValues = abi.encodeWithSignature(
"getOracleNumericValueFromTxMsg(bytes32)",
bytes32("BTC")
sourceAdapter = new TestedSourceAdapter(
IAggregatorV3Source(address(redstoneOracle))
);
}

bytes memory encodedFunctionNumericWithRedstonePayload = abi
.encodePacked(encodedFunctionNumericValues, redstonePayload);
function pushPrice() internal returns (uint256) {
bytes memory data = getRedstonePayload("BTC");

(bool success2, bytes memory dataa) = address(redstoneOracle).call(
encodedFunctionNumericWithRedstonePayload
);

uint256 oracleValue;
if (success2) {
oracleValue = abi.decode(dataa, (uint256));
}
(
bytes memory redstonePayload,
uint256 timestampMilliseconds,
uint256 updatePrice
) = abi.decode(data, (bytes, uint256, uint256));

bytes memory encodedFunction = abi.encodeWithSignature(
"updateDataFeedsValues(uint256)",
Expand All @@ -70,16 +58,13 @@ contract RedstoneOracleAdapterTest is
redstonePayload
);

(bool success, ) = address(redstoneOracle).call(
encodedFunctionWithRedstonePayload
);
// (bool success3, ) = address(redstoneOracle).call(
// encodedFunctionWithRedstonePayload
// );
address(redstoneOracle).call(encodedFunctionWithRedstonePayload);

assert(success);
// assert(success3);
return updatePrice;
}

function testPushPrice() public {
uint256 updatePrice = pushPrice();
(
uint80 roundId,
int256 answer,
Expand All @@ -88,40 +73,34 @@ contract RedstoneOracleAdapterTest is
uint80 answeredInRound
) = redstoneOracle.latestRoundData();

console.logInt(answer);
console.logUint(oracleValue);
console.logBytes(dataa);

// assertEq(roundId, 1);
assertEq(roundId, 1);
assertEq(uint256(answer), updatePrice);
// // assertEq(startedAt, timestampMilliseconds);
// // assertEq(updatedAt, timestampMilliseconds);
// assertEq(answeredInRound, 1);
// assertEq(startedAt, timestampMilliseconds);
// assertEq(updatedAt, timestampMilliseconds);
assertEq(answeredInRound, 1);
}

function testCorrectlyStandardizesOutputs() public {
uint256 pushedPrice = pushPrice();
(
,
int256 latestChainlinkAnswer,
,
uint256 latestChainlinkTimestamp,

) = redstoneOracle.latestRoundData();
(
int256 latestSourceAnswer,
uint256 latestSourceTimestamp
) = sourceAdapter.getLatestSourceData();
assertTrue(
scaleChainlinkTo18(latestChainlinkAnswer) == latestSourceAnswer
);
assertTrue(pushedPrice == uint256(latestChainlinkAnswer));
assertTrue(latestSourceTimestamp == latestChainlinkTimestamp);
}

function getAuthorisedSignerIndex(
address signerAddress
) public view virtual override returns (uint8) {
if (signerAddress == 0x8BB8F32Df04c8b654987DAaeD53D6B6091e3B774) {
return 0;
} else if (
signerAddress == 0xdEB22f54738d54976C4c0fe5ce6d408E40d88499
) {
return 1;
} else if (
signerAddress == 0x51Ce04Be4b3E32572C4Ec9135221d0691Ba7d202
) {
return 2;
} else if (
signerAddress == 0xDD682daEC5A90dD295d14DA4b0bec9281017b5bE
) {
return 3;
} else if (
signerAddress == 0x9c5AE89C4Af6aA32cE58588DBaF90d18a855B6de
) {
return 4;
} else {
revert SignerNotAuthorised(signerAddress);
}
function scaleChainlinkTo18(int256 input) public pure returns (int256) {
return (input * 10 ** 18) / 10 ** 8;
}
}

0 comments on commit 26c33a1

Please sign in to comment.