Skip to content

Commit

Permalink
test(truflation): add tests for Truflation feed
Browse files Browse the repository at this point in the history
- Added 6 tests according to BAC-51
- Added `config/truflationFeed.json` for tests
configuration
  • Loading branch information
arthurka-o committed May 21, 2024
1 parent d8b28bc commit b79c738
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
12 changes: 12 additions & 0 deletions config/truflationFeed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"answerValueCeiling": 1815634312,
"answerValueFloor": 1615634312,
"blockNumber": 44706000,
"feedAddress": "0x1594F325afc4f8dc4E4ad0A3F758f48B1F72930a",
"heartbeat": 4000,
"macroWindowCeiling": 153218490000000000,
"macroWindowFloor": 133218490000000000,
"microWindowCeiling": 152860000000000000,
"microWindowFloor": 132860000000000000,
"roundCount": 10
}
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ test = "tests"
script = "scripts"
out = "forge-out"
libs = ["lib"]
fs_permissions = [{ access = "read", path = "./config"}]

remappings = [
"@openzeppelin/=lib/openzeppelin-contracts/",
Expand Down
132 changes: 132 additions & 0 deletions tests/feeds/chainlink/TruflationFeed.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
pragma solidity 0.8.10;

import "forge-std/StdJson.sol";
import {Test, console2} from "forge-std/Test.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "../../../contracts/feeds/chainlink/OverlayV1ChainlinkFeed.sol";
import "../../../contracts/libraries/Oracle.sol";

contract TruflationFeedTest is Test {
using Oracle for Oracle.Data;
using stdJson for string;

function append(string memory a, string memory b) internal pure returns (string memory) {
return string(abi.encodePacked(a, b));
}

struct JsonConfig {
uint256 answerValueCeiling;
uint256 answerValueFloor;
uint64 blockNumber;
address feedAddress;
uint256 heartbeat;
uint256 macroWindowCeiling;
uint256 macroWindowFloor;
uint256 microWindowCeiling;
uint256 microWindowFloor;
uint8 roundCount;
}

string truflationRPC;
JsonConfig config;
AggregatorV3Interface feed;

function setUp() public {
string memory root = vm.projectRoot();
string memory path = append(root, "/config/truflationFeed.json");
string memory json = vm.readFile(path);
bytes memory jsonBytes = json.parseRaw("");

config = abi.decode(jsonBytes, (JsonConfig));
feed = AggregatorV3Interface(config.feedAddress);

truflationRPC = vm.envString("TRUFLATION_RPC");
vm.createSelectFork(truflationRPC, config.blockNumber);
}

function test_ConsecutiveRoundId() public {
(uint80 latestRoundId,,,,) = feed.latestRoundData();
uint256 updatedAt;
uint256 previousUpdatedAt = type(uint256).max;

for (uint80 index = latestRoundId; index > latestRoundId - config.roundCount; index--) {
(,,, updatedAt,) = feed.getRoundData(index);

assertLe(updatedAt, previousUpdatedAt);
previousUpdatedAt = updatedAt;
}
}

function test_AnswerValue() public {
(uint80 latestRoundId,,,,) = feed.latestRoundData();

for (uint80 index = latestRoundId; index > latestRoundId - config.roundCount; index--) {
(,,, uint256 answer,) = feed.getRoundData(index);

assertGt(answer, config.answerValueFloor);
assertLt(answer, config.answerValueCeiling);
}
}

// we check last n rounds and see if timestamps are not bigger than the current block.timestamp
function test_TimestampsInSeconds() public {
(uint80 latestRoundId,,,,) = feed.latestRoundData();
uint256 updatedAt;
uint256 startedAt;

for (uint80 index = latestRoundId; index > latestRoundId - config.roundCount; index--) {
(,, startedAt, updatedAt,) = feed.getRoundData(index);

int256 updatedAtDiff = int256(block.timestamp) - int256(updatedAt);
int256 startedAtDiff = int256(block.timestamp) - int256(startedAt);

assertGt(updatedAtDiff, 0);
assertGt(startedAtDiff, 0);
}
}

function test_Heartbeat() public {
(uint80 latestRoundId,,,,) = feed.latestRoundData();
uint256 updatedAt;
uint256 previousUpdatedAt = block.timestamp;

for (uint80 index = latestRoundId; index > latestRoundId - config.roundCount; index--) {
(,,, updatedAt,) = feed.getRoundData(index);

assertLt(previousUpdatedAt - updatedAt, config.heartbeat);
previousUpdatedAt = updatedAt;
}
}

function test_AnsweredInRoundCompatability() public {
(uint80 latestRoundId,,,,) = feed.latestRoundData();
uint256 answeredInRound;

for (uint80 index = latestRoundId; index > latestRoundId - config.roundCount; index--) {
(,,,, answeredInRound) = feed.getRoundData(index);

uint80 expectedAnsweredInRound = uint80(answeredInRound);
assertEq(answeredInRound, expectedAnsweredInRound);
}
}

function test_TWAP() public {
for (uint80 index = 0; index < config.roundCount; index++) {
vm.createSelectFork(truflationRPC, config.blockNumber - index);

OverlayV1ChainlinkFeed wrappedFeed = new OverlayV1ChainlinkFeed(
address(0), config.feedAddress, 600, 3600, config.heartbeat
);

Oracle.Data memory data = wrappedFeed.latest();

console2.log("Price over macro window: ", data.priceOverMacroWindow);
console2.log("Price over micro window: ", data.priceOverMicroWindow);

assertGt(data.priceOverMicroWindow, config.microWindowFloor);
assertLt(data.priceOverMicroWindow, config.microWindowCeiling);
assertGt(data.priceOverMacroWindow, config.macroWindowFloor);
assertLt(data.priceOverMacroWindow, config.macroWindowCeiling);
}
}
}

0 comments on commit b79c738

Please sign in to comment.