creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/citizens/OperatorSkillLevels.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\npragma solidity ^0.8.25;\r\n\r\nimport {IPassportUtils} from \"../utils/IPassportUtils.sol\";\r\n\r\n/**\r\n *        ---------::::\r\n *     ---------:---::::::\r\n *   -----------::---:::::::\r\n *  ------------:.:--::::::::\r\n * -------------: .:--::::::::\r\n * -------------:   .:::::::::\r\n * -------------:.......::::::\r\n * -----:..    .:-------::::::\r\n * --------:.. .:-------::::::\r\n * ----------:..:--------:::::\r\n *  -----------.:--------::::\r\n *   ----------::--------:::\r\n *     -------------------\r\n *        -------------\r\n *\r\n *         Nation3 DAO\r\n *     https://nation3.org\r\n */\r\ncontract OperatorSkillLevels {\r\n    string public constant VERSION = \"0.7.0\";\r\n    address public owner;\r\n    mapping(address => uint256) public skillLevelAverages;\r\n    mapping(address => uint8) public skillLevelRatingsCount;\r\n    mapping(address => uint256) private skillLevelRatingsSum;\r\n    mapping(address => mapping(address => uint8)) public skillLevelRatings;\r\n    IPassportUtils public passportUtils;\r\n\r\n    error NotPassportOwner(address illegalAlien);\r\n    error PassportExpired(address citizen);\r\n    error RatingValueError(uint8 rating);\r\n\r\n    event Rated(address operator, uint8 rating, address citizen);\r\n\r\n    constructor(address passportUtils_) {\r\n        owner = address(msg.sender);\r\n        passportUtils = IPassportUtils(passportUtils_);\r\n    }\r\n\r\n    function setOwner(address owner_) public {\r\n        require(msg.sender == owner, \"You are not the owner\");\r\n        owner = owner_;\r\n    }\r\n\r\n    function setPassportUtils(address passportUtils_) public {\r\n        require(msg.sender == owner, \"You are not the owner\");\r\n        passportUtils = IPassportUtils(passportUtils_);\r\n    }\r\n\r\n    /**\r\n     * @notice Rate an operator's skills, on a scale from 1 to 5.\r\n     * @dev Only citizens with a valid passport can rate operators.\r\n     */\r\n    function rate(address operator, uint8 rating) public {\r\n        if (!passportUtils.isOwner(msg.sender)) {\r\n            revert NotPassportOwner(msg.sender);\r\n        }\r\n        if (passportUtils.isExpired(msg.sender)) {\r\n            revert PassportExpired(msg.sender);\r\n        }\r\n        if (\r\n            (rating != 1) &&\r\n            (rating != 2) &&\r\n            (rating != 3) &&\r\n            (rating != 4) &&\r\n            (rating != 5)\r\n        ) {\r\n            revert RatingValueError(rating);\r\n        }\r\n\r\n        uint256 ratingInGwei = rating * 1 ether;\r\n\r\n        if (skillLevelRatings[operator][msg.sender] == 0) {\r\n            skillLevelRatingsCount[operator] += 1;\r\n            skillLevelRatingsSum[operator] += ratingInGwei;\r\n        } else {\r\n            uint256 previousRatingInGwei = skillLevelRatings[operator][\r\n                msg.sender\r\n            ] * 1 ether;\r\n            if (previousRatingInGwei != ratingInGwei) {\r\n                skillLevelRatingsSum[operator] -= previousRatingInGwei;\r\n                skillLevelRatingsSum[operator] += ratingInGwei;\r\n            }\r\n        }\r\n        uint256 newSkillLevelAverage = skillLevelRatingsSum[operator] /\r\n            skillLevelRatingsCount[operator];\r\n\r\n        skillLevelAverages[operator] = newSkillLevelAverage;\r\n        skillLevelRatings[operator][msg.sender] = rating;\r\n        emit Rated(operator, rating, msg.sender);\r\n    }\r\n}\r\n"
      },
      "contracts/utils/IPassportUtils.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\npragma solidity ^0.8.25;\r\n\r\n/**\r\n *        ---------::::\r\n *     ---------:---::::::\r\n *   -----------::---:::::::\r\n *  ------------:.:--::::::::\r\n * -------------: .:--::::::::\r\n * -------------:   .:::::::::\r\n * -------------:.......::::::\r\n * -----:..    .:-------::::::\r\n * --------:.. .:-------::::::\r\n * ----------:..:--------:::::\r\n *  -----------.:--------::::\r\n *   ----------::--------:::\r\n *     -------------------\r\n *        -------------\r\n *\r\n *         Nation3 DAO\r\n *     https://nation3.org\r\n */\r\ninterface IPassportUtils {\r\n    /**\r\n     * Returns `true` if an account is the owner of a passport.\r\n     */\r\n    function isOwner(address account) external view returns (bool);\r\n\r\n    /**\r\n     * Returns the owner of a passport.\r\n     *\r\n     * @param passportID The identifier of an NFT passport\r\n     */\r\n    function getOwnerAddress(uint16 passportID) external view returns (address);\r\n\r\n    /**\r\n     * Returns `true` if a citizen's passport has become revocable.\r\n     *\r\n     * @param citizen The address of an NFT passport's owner\r\n     */\r\n    function isExpired(address citizen) external view returns (bool);\r\n\r\n    /**\r\n     * Returns the Unix epoch time when a citizen's passport will become revocable.\r\n     *\r\n     * @param citizen The address of an NFT passport's owner\r\n     */\r\n    function getExpirationTimestamp(\r\n        address citizen\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * Calculates the Unix epoch time when vote-escrowed `$NATION` will drop below a given threshold.\r\n     *\r\n     * @param lockAmount The amount of `$NATION` tokens that were locked\r\n     * @param lockEnd The lock expiration date in seconds\r\n     * @param votingEscrowThreshold The vote-escrowed `$NATION` balance when a passport will become revocable\r\n     * @return Timestamp in seconds, or `0` if the lock amount is below the threshold\r\n     */\r\n    function calculateThresholdTimestamp(\r\n        uint256 lockAmount,\r\n        uint256 lockEnd,\r\n        uint256 votingEscrowThreshold\r\n    ) external view returns (uint256);\r\n}\r\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}