It is also possible that std. dev could be higher than mean value.( For scores [1,1,1,1,10]->mean =2.8 ,std= 3.6 ).
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import "contracts/llm/LLMOracleCoordinator.sol";
import {LLMOracleRegistry, LLMOracleKind} from "contracts/llm/LLMOracleRegistry.sol";
import {LLMOracleTaskParameters, LLMOracleTask} from "contracts/llm/LLMOracleTask.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
contract MockToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}
contract LLMOracleCoordinatorTest is Test {
LLMOracleCoordinator coordinator;
LLMOracleRegistry registry;
MockToken token;
address dria;
address requester;
address[] generators;
address[] validators;
uint256 taskId;
uint256 constant SUPPLY = 100000 ether;
function setUp() public {
dria = address(this);
requester = address(0x1);
generators.push(address(0x2));
generators.push(address(0x3));
generators.push(address(0x4));
validators.push(address(0x5));
validators.push(address(0x6));
validators.push(address(0x7));
token = new MockToken("WETH", "WETH");
LLMOracleRegistry impl1 = new LLMOracleRegistry();
ERC1967Proxy proxy = new ERC1967Proxy(address(impl1), "");
registry = LLMOracleRegistry(address(proxy));
LLMOracleCoordinator impl2 = new LLMOracleCoordinator();
ERC1967Proxy proxy2 = new ERC1967Proxy(address(impl2), "");
coordinator = LLMOracleCoordinator(address(proxy2));
registry.initialize(1 ether, 1 ether, address(token));
coordinator.initialize(address(registry), address(token), 0.001 ether, 0.001 ether, 0.001 ether);
for (uint256 i = 0; i < 3; i++) {
token.mint(generators[i], 100 ether);
vm.startPrank(generators[i]);
token.approve(address(registry), 100 ether);
registry.register(LLMOracleKind.Generator);
}
vm.stopPrank();
for (uint256 i = 0; i < 3; i++) {
token.mint(validators[i], 100 ether);
vm.startPrank(validators[i]);
token.approve(address(registry), 100 ether);
registry.register(LLMOracleKind.Validator);
}
vm.stopPrank();
}
function testVarianceUnderflow() public {
token.approve(address(coordinator), 100 ether);
token.mint(address(this), 100 ether);
LLMOracleTaskParameters memory param = LLMOracleTaskParameters({
difficulty: 1,
numGenerations: 2,
numValidations: 2
});
coordinator.request("PROTOCOL", "What is 2 + 2?", "gpt", param);
for (uint256 i = 0; i < 2; i++) {
vm.startPrank(generators[i]);
coordinator.respond(1, 1, "4", "");
}
uint[] memory scores = new uint[]();
scores[0]= 100000;
scores[1]=100000;
vm.startPrank(validators[0]);
coordinator.validate(1, 1111111111, scores, "");
uint[] memory scores2 = new uint[]();
scores[0]= 200000;
scores[1]=200000;
vm.startPrank(validators[1]);
coordinator.validate(1, 2222222, scores2, "");
}
}
Update these calculations to prevent underflows.
function variance(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
mean = avg(data);
uint256 sum = 0;
for (uint256 i = 0; i < data.length; i++) {
- uint256 diff = data[i] - mean;
+ uint256 diff = data[i] >= mean ? data[i] - mean : mean - data[i];
sum += diff * diff;
}
+ uint256 lowerBound = _stddev > _mean ? 0 : _mean - _stddev;
+ uint256 upperBound = _mean + _stddev;
for (uint256 v_i = 0; v_i < task.parameters.numValidations; ++v_i) {
uint256 score = scores[v_i];
- if ((score >= _mean - _stddev) && (score <= _mean + _stddev)) {
+ if ((score >=lowerBound) && (score <= upperBound)) {
- if (generationScores[g_i] >= mean - generationDeviationFactor * stddev) {
+ uint256 lower=mean > ( generationDeviationFactor * stddev)? mean - generationDeviationFactor * stddev:0;
+ if (generationScores[g_i] >=lower) {