CogniSignal.t.sol
1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.13; 3 4 import {Test} from "forge-std/Test.sol"; 5 import {Vm} from "forge-std/Vm.sol"; 6 import {CogniSignal} from "../../src/CogniSignal.sol"; 7 8 contract CogniSignalTest is Test { 9 CogniSignal public signal; 10 address public constant DAO = address(0x123); 11 address public constant NOT_DAO = address(0x456); 12 13 event CogniAction( 14 address indexed dao, 15 uint256 indexed chainId, 16 string repo, 17 string action, 18 string target, 19 uint256 pr, 20 bytes32 commit, 21 bytes extra, 22 address indexed executor 23 ); 24 25 function setUp() public { 26 signal = new CogniSignal(DAO); 27 } 28 29 function test_Constructor() public view { 30 assertEq(signal.DAO(), DAO); 31 } 32 33 function test_Signal_Success() public { 34 string memory repo = "Cogni-DAO/test-repo"; 35 string memory action = "PR_APPROVE"; 36 string memory target = "main"; 37 uint256 pr = 123; 38 bytes32 commit = keccak256("commit123"); 39 bytes memory extra = abi.encode(1, block.timestamp + 1 hours, '{"approved": true}'); 40 41 vm.prank(DAO); 42 43 vm.expectEmit(true, true, true, true); 44 emit CogniAction(DAO, block.chainid, repo, action, target, pr, commit, extra, DAO); 45 46 signal.signal(repo, action, target, pr, commit, extra); 47 } 48 49 function test_Signal_RevertWhen_NotDAO() public { 50 vm.prank(NOT_DAO); 51 vm.expectRevert("NOT_DAO"); 52 signal.signal("repo", "action", "target", 0, bytes32(0), ""); 53 } 54 55 function test_Signal_EventFields() public { 56 string memory repo = "Cogni-DAO/cogni-signal-evm-contracts"; 57 string memory action = "PR_APPROVE"; 58 string memory target = "feature/new-feature"; 59 uint256 pr = 42; 60 bytes32 commit = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; 61 uint256 nonce = 1; 62 uint256 deadline = block.timestamp + 1 hours; 63 string memory paramsJson = '{"reviewers": ["alice", "bob"], "required": 2}'; 64 bytes memory extra = abi.encode(nonce, deadline, paramsJson); 65 66 vm.prank(DAO); 67 68 vm.recordLogs(); 69 signal.signal(repo, action, target, pr, commit, extra); 70 71 Vm.Log[] memory logs = vm.getRecordedLogs(); 72 assertEq(logs.length, 1); 73 assertEq(logs[0].topics.length, 4); 74 assertEq(logs[0].topics[0], keccak256("CogniAction(address,uint256,string,string,string,uint256,bytes32,bytes,address)")); 75 assertEq(logs[0].topics[1], bytes32(uint256(uint160(DAO)))); 76 assertEq(logs[0].topics[2], bytes32(block.chainid)); 77 assertEq(logs[0].topics[3], bytes32(uint256(uint160(DAO)))); 78 } 79 80 function test_Signal_MultipleActions() public { 81 vm.startPrank(DAO); 82 83 signal.signal("repo1", "PR_APPROVE", "main", 1, bytes32(uint256(1)), ""); 84 signal.signal("repo2", "PR_APPROVE", "dev", 2, bytes32(uint256(2)), ""); 85 86 vm.stopPrank(); 87 } 88 89 function testFuzz_Signal_Parameters( 90 string memory repo, 91 string memory action, 92 string memory target, 93 uint256 pr, 94 bytes32 commit, 95 bytes memory extra 96 ) public { 97 vm.prank(DAO); 98 99 vm.expectEmit(true, true, true, true); 100 emit CogniAction(DAO, block.chainid, repo, action, target, pr, commit, extra, DAO); 101 102 signal.signal(repo, action, target, pr, commit, extra); 103 } 104 105 function test_ExtraData_Encoding() public view { 106 uint256 nonce = 123; 107 uint256 deadline = block.timestamp + 3600; 108 string memory paramsJson = '{"action": "approve", "required_reviewers": 2}'; 109 110 bytes memory encoded = abi.encode(nonce, deadline, paramsJson); 111 (uint256 decodedNonce, uint256 decodedDeadline, string memory decodedJson) = 112 abi.decode(encoded, (uint256, uint256, string)); 113 114 assertEq(decodedNonce, nonce); 115 assertEq(decodedDeadline, deadline); 116 assertEq(decodedJson, paramsJson); 117 } 118 }