synapsecns/sanguine

View on GitHub
packages/contracts-core/test/utils/SynapseAgents.t.sol

Summary

Maintainability
Test Coverage
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {
    ATTESTATION_VALID_SALT,
    ATTESTATION_INVALID_SALT,
    RECEIPT_VALID_SALT,
    RECEIPT_INVALID_SALT,
    SNAPSHOT_VALID_SALT,
    STATE_INVALID_SALT
} from "../../contracts/libs/Constants.sol";

import {SnapshotLib, State, RawAttestation, RawExecReceipt, RawSnapshot, RawState} from "./libs/SynapseStructs.t.sol";

import {SynapseUtilities} from "./SynapseUtilities.t.sol";

import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

// solhint-disable no-empty-blocks
// solhint-disable ordering
abstract contract SynapseAgents is SynapseUtilities {
    struct Domain {
        string name;
        address agent;
        address[] agents;
    }

    // domain => Domain's name
    uint32[] internal allDomains;
    mapping(uint32 => Domain) internal domains;
    mapping(address => uint256) internal agentPK;

    /// @notice Prevents this contract from being included in the coverage report
    function testSynapseAgents() external {}

    function setUp() public virtual {
        // Setup domains and create agents for them
        setupDomain(0, "Guards");
        setupDomain(DOMAIN_LOCAL, "Local");
        setupDomain(DOMAIN_REMOTE, "Remote");
        setupDomain(DOMAIN_OTHER, "Other");
    }

    // ═══════════════════════════════════════════════════ SETUP ═══════════════════════════════════════════════════════

    function setupDomain(uint32 domain, string memory name) public virtual {
        allDomains.push(domain);
        domains[domain].name = name;
        string memory baseAgentName = domain == 0 ? "Guard" : string.concat("Notary(", name, ")");
        domains[domain].agents = new address[](DOMAIN_AGENTS);
        for (uint256 i = 0; i < DOMAIN_AGENTS; ++i) {
            domains[domain].agents[i] = createAgent(string.concat(baseAgentName, " ", Strings.toString(i)));
        }
        domains[domain].agent = domains[domain].agents[0];
    }

    // ══════════════════════════════════════════════════ AGENTS ═══════════════════════════════════════════════════════

    function createAgent(string memory name) public returns (address agent) {
        uint256 privKey;
        (agent, privKey) = makeAddrAndKey(name);
        agentPK[agent] = privKey;
    }

    function getAgent(uint256 domainId, uint256 agentId) public view returns (uint32 domain, address agent) {
        domain = allDomains[domainId % allDomains.length];
        agent = domains[domain].agents[agentId % DOMAIN_AGENTS];
    }

    function getDomainAgent(uint32 domain, uint256 agentId) public view returns (address agent) {
        agent = domains[domain].agents[agentId % DOMAIN_AGENTS];
    }

    function getGuard(uint256 agentId) public view returns (address guard) {
        guard = getDomainAgent(0, agentId);
    }

    function getNotary(uint256 domainId, uint256 agentId) public view returns (address notary) {
        uint32 domain = allDomains[1 + (domainId % (allDomains.length - 1))];
        notary = getDomainAgent(domain, agentId);
    }

    /// @dev Private to enforce using salt-specific signing
    function signMessage(address agent, bytes32 hashedMsg) private view returns (bytes memory signature) {
        uint256 privKey = agentPK[agent];
        require(privKey != 0, "Unknown agent");
        return signMessage(privKey, hashedMsg);
    }

    /// @notice Signs a salted hash of a message
    function signMessage(address agent, bytes32 salt, bytes32 hashedMsg) public view returns (bytes memory signature) {
        return signMessage(agent, keccak256(bytes.concat(salt, hashedMsg)));
    }

    /// @notice Signs hashed message, by using a requested salt.
    function signMessage(address agent, bytes32 salt, bytes memory message)
        public
        view
        returns (bytes memory signature)
    {
        return signMessage(agent, salt, keccak256(message));
    }

    // ════════════════════════════════════════════ SIGNING STATEMENTS ═════════════════════════════════════════════════

    function signAttestation(address agent, bytes memory attestation) public view returns (bytes memory signature) {
        return signMessage(agent, ATTESTATION_VALID_SALT, attestation);
    }

    function signAttestation(address agent, RawAttestation memory ra)
        public
        view
        returns (bytes memory attestation, bytes memory signature)
    {
        attestation = ra.formatAttestation();
        signature = signAttestation(agent, attestation);
    }

    function signAttestationReport(address agent, bytes memory attPayload)
        public
        view
        returns (bytes memory signature)
    {
        return signMessage(agent, ATTESTATION_INVALID_SALT, attPayload);
    }

    function signAttestationReport(address agent, RawAttestation memory ra)
        public
        view
        returns (bytes memory attPayload, bytes memory arSignature)
    {
        attPayload = ra.formatAttestation();
        arSignature = signAttestationReport(agent, attPayload);
    }

    function signReceipt(address agent, bytes memory receipt) public view returns (bytes memory signature) {
        return signMessage(agent, RECEIPT_VALID_SALT, receipt);
    }

    function signReceipt(address agent, RawExecReceipt memory re)
        public
        view
        returns (bytes memory receipt, bytes memory signature)
    {
        receipt = re.formatReceipt();
        signature = signReceipt(agent, receipt);
    }

    function signReceiptReport(address agent, bytes memory rcptPayload) public view returns (bytes memory signature) {
        return signMessage(agent, RECEIPT_INVALID_SALT, rcptPayload);
    }

    function signReceiptReport(address agent, RawExecReceipt memory re)
        public
        view
        returns (bytes memory rcptPayload, bytes memory rrSignature)
    {
        rcptPayload = re.formatReceipt();
        rrSignature = signReceiptReport(agent, rcptPayload);
    }

    function signSnapshot(address agent, bytes memory snapshot) public view returns (bytes memory signature) {
        return signMessage(agent, SNAPSHOT_VALID_SALT, snapshot);
    }

    function signSnapshot(address agent, RawSnapshot memory rawSnap)
        public
        view
        returns (bytes memory snapshot, bytes memory signature)
    {
        snapshot = rawSnap.formatSnapshot();
        signature = signSnapshot(agent, snapshot);
    }

    function signSnapshot(address agent, State[] memory states)
        public
        view
        returns (bytes memory snapshot, bytes memory signature)
    {
        snapshot = SnapshotLib.formatSnapshot(states);
        signature = signSnapshot(agent, snapshot);
    }

    function signStateReport(address agent, bytes memory statePayload) public view returns (bytes memory signature) {
        return signMessage(agent, STATE_INVALID_SALT, statePayload);
    }

    function signStateReport(address agent, RawState memory rs)
        public
        view
        returns (bytes memory statePayload, bytes memory srSignature)
    {
        statePayload = rs.formatState();
        srSignature = signStateReport(agent, statePayload);
    }
}