diff --git a/archives/contracts/services/MetricsPrecompile.sol b/archives/contracts/services/MetricsPrecompile.sol deleted file mode 100644 index 33520ce..0000000 --- a/archives/contracts/services/MetricsPrecompile.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Metrics Precompile Contract -/// @notice This contract interacts with the Tangle blockchain's runtime to fetch metrics data -interface MetricsPrecompile { - /// @notice Fetch the job creation time from the Tangle blockchain - /// @param jobId Unique identifier of the job - /// @return Timestamp of when the job was created - function getJobCreationTime(bytes32 jobId) external view returns (uint256); - - /// @notice Fetch the job execution submission time from the Tangle blockchain - /// @param jobId Unique identifier of the job - /// @return Timestamp of when the job execution was submitted - function getJobExecutionSubmissionTime(bytes32 jobId) external view returns (uint256); - - /// @notice Fetch the job execution verification time from the Tangle blockchain - /// @param jobId Unique identifier of the job - /// @return Timestamp of when the job execution was verified - function getJobExecutionVerificationTime(bytes32 jobId) external view returns (uint256); - - /// @notice Fetch the address of the operator who submitted the job execution - /// @param jobId Unique identifier of the job - /// @return Address of the operator who submitted the job execution - function getJobExecutionSubmitter(bytes32 jobId) external view returns (address); - - /// @notice Fetch the number of failed job executions - /// @param jobId Unique identifier of the job - /// @return Number of failed job executions - function getFailedJobExecutions(bytes32 jobId) external view returns (uint256); - - /// @notice Check if a service meets its QoS standards - /// @param serviceId Unique identifier of the service - /// @return Boolean indicating whether the service meets its QoS standards - function checkImOnline(bytes32 serviceId) external view returns (bool); -} diff --git a/archives/contracts/services/MetricsSystem.sol b/archives/contracts/services/MetricsSystem.sol deleted file mode 100644 index 4be917b..0000000 --- a/archives/contracts/services/MetricsSystem.sol +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import "openzeppelin-contracts/access/Ownable.sol"; -import "core/services/metrics/IMetricComputation.sol"; - -/// @title MetricsSystem -/// @notice This contract manages a system for tracking and analyzing metrics for various blueprints and operators -contract MetricsSystem is Ownable { - struct Metric { - string name; - uint8 decimals; - bool isActive; - } - - struct MetricValue { - uint256 value; - uint256 timestamp; - } - - struct DerivedMetric { - string name; - bool isActive; - uint256[] sourceMetricIndices; - IMetricComputation computationContract; - } - - /// @notice Mapping of blueprint IDs to their metrics - mapping(bytes32 => Metric[]) public blueprintMetrics; - - /// @notice Mapping of blueprint IDs to their derived metrics - mapping(bytes32 => DerivedMetric[]) public blueprintDerivedMetrics; - - /// @notice Mapping of blueprint IDs to operator addresses to metric indices to metric value histories - mapping(bytes32 => mapping(address => mapping(uint256 => MetricValue[]))) public operatorMetrics; - - /// @notice Mapping of blueprint IDs to operator addresses to derived metric indices to the latest derived metric value - mapping(bytes32 => mapping(address => mapping(uint256 => MetricValue))) public operatorDerivedMetrics; - - uint256 public constant MAX_HISTORY = 100; // Maximum number of historical values to store - - event MetricAdded(bytes32 indexed blueprintId, uint256 indexed metricIndex, string name, uint8 decimals); - event MetricRemoved(bytes32 indexed blueprintId, uint256 indexed metricIndex); - event DerivedMetricAdded( - bytes32 indexed blueprintId, - uint256 indexed derivedMetricIndex, - string name, - uint256[] sourceMetricIndices, - address computationContract - ); - event DerivedMetricRemoved(bytes32 indexed blueprintId, uint256 indexed derivedMetricIndex); - event MetricReported(bytes32 indexed blueprintId, address indexed operator, uint256 indexed metricIndex, uint256 value); - event DerivedMetricUpdated( - bytes32 indexed blueprintId, address indexed operator, uint256 indexed derivedMetricIndex, uint256 value - ); - - /// @notice Adds a new metric to a blueprint - /// @param blueprintId The unique identifier of the blueprint - /// @param name The name of the metric - /// @param decimals The number of decimal places for the metric - function addMetric(bytes32 blueprintId, string memory name, uint8 decimals) external onlyOwner { - uint256 metricIndex = blueprintMetrics[blueprintId].length; - blueprintMetrics[blueprintId].push(Metric(name, decimals, true)); - emit MetricAdded(blueprintId, metricIndex, name, decimals); - } - - /// @notice Removes a metric from a blueprint by setting it as inactive - /// @param blueprintId The unique identifier of the blueprint - /// @param metricIndex The index of the metric to be removed - function removeMetric(bytes32 blueprintId, uint256 metricIndex) external onlyOwner { - require(metricIndex < blueprintMetrics[blueprintId].length, "Invalid metric index"); - blueprintMetrics[blueprintId][metricIndex].isActive = false; - emit MetricRemoved(blueprintId, metricIndex); - } - - /// @notice Adds a new derived metric to a blueprint - /// @param blueprintId The unique identifier of the blueprint - /// @param name The name of the derived metric - /// @param sourceMetricIndices The indices of the source metrics used to calculate this derived metric - /// @param computationContractAddress The address of the contract that computes this derived metric - function addDerivedMetric( - bytes32 blueprintId, - string memory name, - uint256[] memory sourceMetricIndices, - address computationContractAddress - ) - external - onlyOwner - { - uint256 derivedMetricIndex = blueprintDerivedMetrics[blueprintId].length; - blueprintDerivedMetrics[blueprintId].push( - DerivedMetric(name, true, sourceMetricIndices, IMetricComputation(computationContractAddress)) - ); - emit DerivedMetricAdded(blueprintId, derivedMetricIndex, name, sourceMetricIndices, computationContractAddress); - } - - /// @notice Removes a derived metric from a blueprint by setting it as inactive - /// @param blueprintId The unique identifier of the blueprint - /// @param derivedMetricIndex The index of the derived metric to be removed - function removeDerivedMetric(bytes32 blueprintId, uint256 derivedMetricIndex) external onlyOwner { - require(derivedMetricIndex < blueprintDerivedMetrics[blueprintId].length, "Invalid derived metric index"); - blueprintDerivedMetrics[blueprintId][derivedMetricIndex].isActive = false; - emit DerivedMetricRemoved(blueprintId, derivedMetricIndex); - } - - /// @notice Reports a metric value for a specific blueprint and operator - /// @param blueprintId The unique identifier of the blueprint - /// @param metricIndex The index of the metric being reported - /// @param value The value of the metric being reported - function reportMetric(bytes32 blueprintId, uint256 metricIndex, uint256 value) external { - require(metricIndex < blueprintMetrics[blueprintId].length, "Invalid metric index"); - require(blueprintMetrics[blueprintId][metricIndex].isActive, "Metric is not active"); - - MetricValue[] storage history = operatorMetrics[blueprintId][msg.sender][metricIndex]; - if (history.length == MAX_HISTORY) { - for (uint256 i = 0; i < MAX_HISTORY - 1; i++) { - history[i] = history[i + 1]; - } - history[MAX_HISTORY - 1] = MetricValue(value, block.timestamp); - } else { - history.push(MetricValue(value, block.timestamp)); - } - - emit MetricReported(blueprintId, msg.sender, metricIndex, value); - } - - /// @notice Computes and updates a derived metric for a specific blueprint and operator - /// @param blueprintId The unique identifier of the blueprint - /// @param operator The address of the operator - /// @param derivedMetricIndex The index of the derived metric to compute - function computeDerivedMetric(bytes32 blueprintId, address operator, uint256 derivedMetricIndex) external { - require(derivedMetricIndex < blueprintDerivedMetrics[blueprintId].length, "Invalid derived metric index"); - require(blueprintDerivedMetrics[blueprintId][derivedMetricIndex].isActive, "Derived metric is not active"); - - DerivedMetric storage derivedMetric = blueprintDerivedMetrics[blueprintId][derivedMetricIndex]; - uint256[] memory sourceMetrics = derivedMetric.sourceMetricIndices; - - // Count total values across all source metrics - uint256 totalValues = 0; - for (uint256 i = 0; i < sourceMetrics.length; i++) { - totalValues += operatorMetrics[blueprintId][operator][sourceMetrics[i]].length; - } - - // Create arrays to hold all values and timestamps - uint256[] memory values = new uint256[](totalValues); - uint256[] memory timestamps = new uint256[](totalValues); - uint256 valueIndex = 0; - - // Populate values and timestamps arrays - for (uint256 i = 0; i < sourceMetrics.length; i++) { - MetricValue[] storage history = operatorMetrics[blueprintId][operator][sourceMetrics[i]]; - for (uint256 j = 0; j < history.length; j++) { - values[valueIndex] = history[j].value; - timestamps[valueIndex] = history[j].timestamp; - valueIndex++; - } - } - - // Compute the derived metric - uint256 result = IMetricComputation(derivedMetric.computationContract).compute(values, timestamps); - - // Store the result - operatorDerivedMetrics[blueprintId][operator][derivedMetricIndex] = - MetricValue({ value: result, timestamp: block.timestamp }); - - emit DerivedMetricUpdated(blueprintId, operator, derivedMetricIndex, result); - } - - /// @notice Retrieves a specific metric for a blueprint - /// @param blueprintId The unique identifier of the blueprint - /// @param metricIndex The index of the metric - /// @return The Metric struct containing the metric details - function getMetric(bytes32 blueprintId, uint256 metricIndex) external view returns (Metric memory) { - require(metricIndex < blueprintMetrics[blueprintId].length, "Invalid metric index"); - return blueprintMetrics[blueprintId][metricIndex]; - } - - /// @notice Retrieves a specific derived metric for a blueprint - /// @param blueprintId The unique identifier of the blueprint - /// @param derivedMetricIndex The index of the derived metric - /// @return The DerivedMetric struct containing the derived metric details - function getDerivedMetric(bytes32 blueprintId, uint256 derivedMetricIndex) external view returns (DerivedMetric memory) { - require(derivedMetricIndex < blueprintDerivedMetrics[blueprintId].length, "Invalid derived metric index"); - return blueprintDerivedMetrics[blueprintId][derivedMetricIndex]; - } - - /// @notice Retrieves the metric value history for a specific operator and blueprint - /// @param blueprintId The unique identifier of the blueprint - /// @param operator The address of the operator - /// @param metricIndex The index of the metric - /// @return An array of MetricValue structs containing the value history - function getOperatorMetricHistory( - bytes32 blueprintId, - address operator, - uint256 metricIndex - ) - external - view - returns (MetricValue[] memory) - { - return operatorMetrics[blueprintId][operator][metricIndex]; - } - - /// @notice Retrieves the latest derived metric value for a specific operator and blueprint - /// @param blueprintId The unique identifier of the blueprint - /// @param operator The address of the operator - /// @param derivedMetricIndex The index of the derived metric - /// @return The MetricValue struct containing the latest derived value and timestamp - function getOperatorDerivedMetric( - bytes32 blueprintId, - address operator, - uint256 derivedMetricIndex - ) - external - view - returns (MetricValue memory) - { - return operatorDerivedMetrics[blueprintId][operator][derivedMetricIndex]; - } -} diff --git a/archives/contracts/services/metrics/Averages.sol b/archives/contracts/services/metrics/Averages.sol deleted file mode 100644 index 68d221c..0000000 --- a/archives/contracts/services/metrics/Averages.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import { IMetricComputation } from "./IMetricComputation.sol"; -import { exp, div, mul } from "prb-math/ud60x18/Math.sol"; -import { add } from "prb-math/ud60x18/Helpers.sol"; -import { LOG2_E } from "prb-math/ud60x18/Constants.sol"; -import { UD60x18 } from "prb-math/ud60x18/ValueType.sol"; - -contract SimpleMovingAverage is IMetricComputation { - uint256 public immutable period; - - constructor(uint256 _period) { - require(_period > 0, "Period must be greater than 0"); - period = _period; - } - - function compute(uint256[] memory values, uint256[] memory) external view override returns (uint256) { - require(values.length > 0, "No data"); - uint256 sum = 0; - uint256 count = min(values.length, period); - for (uint256 i = values.length - count; i < values.length; i++) { - sum += values[i]; - } - return count > 0 ? sum / count : 0; - } - - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} - -contract WeightedMovingAverage is IMetricComputation { - uint256[] public weights; - uint256 public immutable totalWeight; - - constructor(uint256[] memory _weights) { - require(_weights.length > 0, "Weights array must not be empty"); - weights = _weights; - uint256 _totalWeight = 0; - for (uint256 i = 0; i < _weights.length; i++) { - _totalWeight += _weights[i]; - } - totalWeight = _totalWeight; - } - - function compute(uint256[] memory values, uint256[] memory) external view override returns (uint256) { - require(values.length > 0, "No data"); - uint256 weightedSum = 0; - uint256 usedWeights = 0; - for (uint256 i = 0; i < min(values.length, weights.length); i++) { - uint256 value = values[values.length - i - 1]; - uint256 weight = weights[weights.length - i - 1]; - weightedSum += value * weight; - usedWeights += weight; - } - return usedWeights > 0 ? weightedSum / usedWeights : 0; - } - - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} - -contract ExponentialMovingAverage is IMetricComputation { - uint256 public immutable alpha; - uint256 public constant SCALE = 1e18; - - constructor(uint256 _alpha) { - require(_alpha > 0 && _alpha <= SCALE, "Alpha must be between 0 and 1e18"); - alpha = _alpha; - } - - function compute(uint256[] memory values, uint256[] memory) external view override returns (uint256) { - require(values.length > 0, "No data"); - - UD60x18 ema = UD60x18.wrap(values[0]); - UD60x18 alphaUD = UD60x18.wrap(alpha); - UD60x18 oneMinusAlpha = UD60x18.wrap(SCALE - alpha); - - for (uint256 i = 1; i < values.length; i++) { - // EMA = alpha * value + (1 - alpha) * EMA - ema = add(mul(alphaUD, UD60x18.wrap(values[i])), mul(oneMinusAlpha, ema)); - } - - return ema.unwrap(); - } -} diff --git a/archives/contracts/services/metrics/IMetricComputation.sol b/archives/contracts/services/metrics/IMetricComputation.sol deleted file mode 100644 index 49df638..0000000 --- a/archives/contracts/services/metrics/IMetricComputation.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -interface IMetricComputation { - function compute(uint256[] memory values, uint256[] memory timestamps) external view returns (uint256); -} diff --git a/archives/test/services/MetricsSystemAveragesTest.t.sol b/archives/test/services/MetricsSystemAveragesTest.t.sol deleted file mode 100644 index 9f84951..0000000 --- a/archives/test/services/MetricsSystemAveragesTest.t.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "forge-std/Test.sol"; -import "../../contracts/services/MetricsSystem.sol"; -import "../../contracts/services/metrics/Averages.sol"; - -contract MetricsSystemAveragesTest is Test { - MetricsSystem public metricsSystem; - SimpleMovingAverage public sma; - WeightedMovingAverage public wma; - ExponentialMovingAverage public ema; - - bytes32 public constant BLUEPRINT_ID = keccak256("TestBlueprint"); - address public constant OPERATOR = address(0x1234); - - function setUp() public { - metricsSystem = new MetricsSystem(); - sma = new SimpleMovingAverage(3); // 3-period SMA - uint256[] memory weights = new uint256[](3); - weights[0] = 1; - weights[1] = 2; - weights[2] = 3; - wma = new WeightedMovingAverage(weights); - ema = new ExponentialMovingAverage(500_000_000_000_000_000); // alpha = 0.5 - } - - function testSimpleMovingAverageSmall() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 2); - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "SMA", sourceIndices, address(sma)); - - vm.startPrank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 200); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 300); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 400); - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - assertEq(derivedValue.value, 300); // Average of 200, 300, 400 - } - - function testSimpleMovingAverageBig() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 18); - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "SMA", sourceIndices, address(sma)); - - vm.startPrank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 200e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 300e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 400e18); - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - assertEq(derivedValue.value, 300e18); // Average of 200e18, 300e18, 400e18 - } - - function testWeightedMovingAverageSmall() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 18); - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "WMA", sourceIndices, address(wma)); - - vm.startPrank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 200e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 300e18); - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - // Expected WMA: (100e18*1 + 200e18*2 + 300e18*3) / (1+2+3) = 233.33e18 - assertApproxEqAbs(derivedValue.value, 233_333_333_333_333_333_333, 1e15); - } - - function testWeightedMovingAverageBig() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 18); - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "WMA", sourceIndices, address(wma)); - - vm.startPrank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 200e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 300e18); - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - // Expected WMA: (100e18*1 + 200e18*2 + 300e18*3) / (1+2+3) = 233.33e18 - assertApproxEqAbs(derivedValue.value, 233_333_333_333_333_333_333, 1e15); - } - - function testExponentialMovingAverage() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 18); - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "EMA", sourceIndices, address(ema)); - - vm.startPrank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 200e18); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 300e18); - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - - // Expected EMA after [100, 200, 300] with alpha 0.5 is 225 - uint256 expectedEMA = 225e18; - assertApproxEqAbs(derivedValue.value, expectedEMA, 1e15); // Allow for small rounding errors - } -} diff --git a/archives/test/services/MetricsSystemEMATest.t.sol b/archives/test/services/MetricsSystemEMATest.t.sol deleted file mode 100644 index c6bc4db..0000000 --- a/archives/test/services/MetricsSystemEMATest.t.sol +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "forge-std/Test.sol"; -import "core/services/MetricsSystem.sol"; -import "core/services/metrics/Averages.sol"; - -contract MetricsSystemAveragesTest is Test { - MetricsSystem public metricsSystem; - ExponentialMovingAverage public ema; - ExponentialMovingAverage public emaFastResponse; - ExponentialMovingAverage public emaSlowResponse; - - bytes32 public constant BLUEPRINT_ID = keccak256("TestBlueprint"); - address public constant OPERATOR = address(0x1234); - - function setUp() public { - metricsSystem = new MetricsSystem(); - ema = new ExponentialMovingAverage(500_000_000_000_000_000); // alpha = 0.5 - emaFastResponse = new ExponentialMovingAverage(800_000_000_000_000_000); // alpha = 0.8 - emaSlowResponse = new ExponentialMovingAverage(200_000_000_000_000_000); // alpha = 0.2 - } - - function testBasicEMA() public { - uint256[] memory values = new uint256[](3); - values[0] = 100e18; - values[1] = 200e18; - values[2] = 300e18; - runEMATest(ema, values, 225e18, "Basic EMA"); - } - - function testFastResponseEMA() public { - uint256[] memory values = new uint256[](3); - values[0] = 100e18; - values[1] = 200e18; - values[2] = 300e18; - runEMATest(emaFastResponse, values, 276e18, "Fast Response EMA"); - } - - function testEMAWithConstantValues() public { - uint256[] memory values = new uint256[](4); - values[0] = 100e18; - values[1] = 100e18; - values[2] = 100e18; - values[3] = 100e18; - runEMATest(ema, values, 100e18, "EMA with Constant Values"); - } - - function testEMAWithDecreasingValues() public { - uint256[] memory values = new uint256[](5); - values[0] = 500e18; - values[1] = 400e18; - values[2] = 300e18; - values[3] = 200e18; - values[4] = 100e18; - runEMATest(ema, values, 193.75e18, "EMA with Decreasing Values"); - } - - function testEMAWithIncreasingValues() public { - uint256[] memory values = new uint256[](5); - values[0] = 100e18; - values[1] = 200e18; - values[2] = 300e18; - values[3] = 400e18; - values[4] = 500e18; - runEMATest(ema, values, 406.25e18, "EMA with Increasing Values"); - } - - function testEMAWithVolatileValues() public { - uint256[] memory values = new uint256[](5); - values[0] = 100e18; - values[1] = 500e18; - values[2] = 50e18; - values[3] = 400e18; - values[4] = 200e18; - runEMATest(ema, values, 243.75e18, "EMA with Volatile Values"); - } - - function testSlowResponseEMA() public { - uint256[] memory values = new uint256[](3); - values[0] = 100e18; - values[1] = 200e18; - values[2] = 300e18; - runEMATest(emaSlowResponse, values, 156e18, "Slow Response EMA"); - } - - function testEMAWithSingleValue() public { - uint256[] memory values = new uint256[](1); - values[0] = 100e18; - runEMATest(ema, values, 100e18, "EMA with Single Value"); - } - - function testEMAWithLargeValues() public { - uint256[] memory values = new uint256[](3); - values[0] = 1e40; - values[1] = 2e40; - values[2] = 3e40; - runEMATest(ema, values, 2.25e40, "EMA with Large Values"); - } - - function testEMAWithSmallValues() public { - uint256[] memory values = new uint256[](3); - values[0] = 1e6; - values[1] = 2e6; - values[2] = 3e6; - runEMATest(ema, values, 2.25e6, "EMA with Small Values"); - } - - function runEMATest( - ExponentialMovingAverage emaContract, - uint256[] memory values, - uint256 expectedEMA, - string memory testName - ) - internal - { - metricsSystem.addMetric(BLUEPRINT_ID, testName, 18); - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, testName, sourceIndices, address(emaContract)); - - vm.startPrank(OPERATOR); - for (uint256 i = 0; i < values.length; i++) { - metricsSystem.reportMetric(BLUEPRINT_ID, 0, values[i]); - } - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - - assertApproxEqRel(derivedValue.value, expectedEMA, 1e15, string(abi.encodePacked("EMA test failed: ", testName))); // 0.1% - // tolerance - } -} diff --git a/archives/test/services/MetricsSystemTest.t.sol b/archives/test/services/MetricsSystemTest.t.sol deleted file mode 100644 index 5eeddf5..0000000 --- a/archives/test/services/MetricsSystemTest.t.sol +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "forge-std/Test.sol"; -import "core/services/MetricsSystem.sol"; -import "core/services/metrics/IMetricComputation.sol"; - -contract MockComputation is IMetricComputation { - function compute(uint256[] memory values, uint256[] memory) external pure override returns (uint256) { - require(values.length > 0, "No values provided"); - uint256 sum = 0; - uint256 count = 0; - for (uint256 i = 0; i < values.length; i++) { - if (values[i] != 0) { - sum += values[i]; - count++; - } - } - return count > 0 ? sum / count : 0; - } -} - -contract MetricsSystemTest is Test { - MetricsSystem public metricsSystem; - MockComputation public mockComputation; - - bytes32 public constant BLUEPRINT_ID = keccak256("TestBlueprint"); - address public constant OPERATOR = address(0x1234); - - function setUp() public { - metricsSystem = new MetricsSystem(); - mockComputation = new MockComputation(); - } - - function testAddMetric() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 2); - MetricsSystem.Metric memory metric = metricsSystem.getMetric(BLUEPRINT_ID, 0); - assertEq(metric.name, "TestMetric"); - assertEq(metric.decimals, 2); - assertTrue(metric.isActive); - } - - function testRemoveMetric() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 2); - metricsSystem.removeMetric(BLUEPRINT_ID, 0); - MetricsSystem.Metric memory metric = metricsSystem.getMetric(BLUEPRINT_ID, 0); - assertFalse(metric.isActive); - } - - function testAddDerivedMetric() public { - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "DerivedMetric", sourceIndices, address(mockComputation)); - MetricsSystem.DerivedMetric memory derivedMetric = metricsSystem.getDerivedMetric(BLUEPRINT_ID, 0); - assertEq(derivedMetric.name, "DerivedMetric"); - assertTrue(derivedMetric.isActive); - assertEq(derivedMetric.sourceMetricIndices.length, 1); - assertEq(derivedMetric.sourceMetricIndices[0], 0); - assertEq(address(derivedMetric.computationContract), address(mockComputation)); - } - - function testRemoveDerivedMetric() public { - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "DerivedMetric", sourceIndices, address(mockComputation)); - metricsSystem.removeDerivedMetric(BLUEPRINT_ID, 0); - MetricsSystem.DerivedMetric memory derivedMetric = metricsSystem.getDerivedMetric(BLUEPRINT_ID, 0); - assertFalse(derivedMetric.isActive); - } - - function testReportMetric() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 2); - vm.prank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100); - MetricsSystem.MetricValue[] memory history = metricsSystem.getOperatorMetricHistory(BLUEPRINT_ID, OPERATOR, 0); - assertEq(history.length, 1); - assertEq(history[0].value, 100); - } - - function testComputeDerivedMetric() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric", 2); - uint256[] memory sourceIndices = new uint256[](1); - sourceIndices[0] = 0; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "DerivedMetric", sourceIndices, address(mockComputation)); - - vm.startPrank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 200); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 300); - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - assertEq(derivedValue.value, 200); // Average of 100, 200, 300 - } - - function testReportMultipleMetrics() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric1", 2); - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric2", 2); - - vm.startPrank(OPERATOR); - for (uint256 i = 0; i < 5; i++) { - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100 + i * 10); - metricsSystem.reportMetric(BLUEPRINT_ID, 1, 200 + i * 20); - } - vm.stopPrank(); - - MetricsSystem.MetricValue[] memory history1 = metricsSystem.getOperatorMetricHistory(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue[] memory history2 = metricsSystem.getOperatorMetricHistory(BLUEPRINT_ID, OPERATOR, 1); - - assertEq(history1.length, 5); - assertEq(history2.length, 5); - assertEq(history1[4].value, 140); - assertEq(history2[4].value, 280); - } - - function testComputeDerivedMetricWithMultipleSources() public { - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric1", 2); - metricsSystem.addMetric(BLUEPRINT_ID, "TestMetric2", 2); - - uint256[] memory sourceIndices = new uint256[](2); - sourceIndices[0] = 0; - sourceIndices[1] = 1; - metricsSystem.addDerivedMetric(BLUEPRINT_ID, "DerivedMetric", sourceIndices, address(mockComputation)); - - vm.startPrank(OPERATOR); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100); - metricsSystem.reportMetric(BLUEPRINT_ID, 1, 200); - vm.stopPrank(); - - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - MetricsSystem.MetricValue memory derivedValue = metricsSystem.getOperatorDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - assertEq(derivedValue.value, 150); // Average of 100 and 200 - } - - function testFailReportInvalidMetric() public { - vm.expectRevert("Invalid metric"); - metricsSystem.reportMetric(BLUEPRINT_ID, 0, 100); - } - - function testFailComputeInvalidDerivedMetric() public { - vm.expectRevert("Invalid derived metric"); - metricsSystem.computeDerivedMetric(BLUEPRINT_ID, OPERATOR, 0); - } -}