polyglot-alpha / scripts /grant_reputation_authority.py
licaomeng
deploy: main@8970ffb → HF Spaces (2026-05-27T05:19Z)
88d2f2a
"""One-shot: grant the operator wallet ``authorized`` on ReputationRegistry.
The deployed ``ReputationRegistry`` contract gates ``updateOnAuction``,
``updateOnQuality``, ``updateOnFee``, and ``slashReputation`` behind an
``onlyAuthorized`` modifier. The contract owner is implicitly authorized
(``msg.sender == owner`` is accepted), and the constructor seeds
``authorized[owner] = true``, so when the operator wallet IS the owner
this script is a no-op and exits 0 without sending a tx.
Usage::
python scripts/grant_reputation_authority.py # operator self
python scripts/grant_reputation_authority.py 0xDeadBeef # explicit grantee
The signer is always the operator wallet (``HACKATHON_WALLET_PRIVATE_KEY``);
the optional positional arg is the *grantee* address. Only the contract
owner can call ``setAuthorized``.
"""
from __future__ import annotations
import argparse
import asyncio
import logging
import os
import sys
from pathlib import Path
# Make ``polyglot_alpha`` importable when run as a plain script.
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError: # pragma: no cover - optional
pass
from web3 import Web3
from polyglot_alpha.chain.reputation_registry import (
is_authorized,
set_authorized,
)
from polyglot_alpha.onchain import OnChainClient
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger("grant_reputation_authority")
def _parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"grantee",
nargs="?",
default=None,
help=(
"Address to grant 'authorized' to. Defaults to "
"HACKATHON_WALLET_ADDRESS (the operator wallet)."
),
)
parser.add_argument(
"--revoke",
action="store_true",
help="Revoke instead of grant (calls setAuthorized(addr, false)).",
)
return parser.parse_args()
async def main() -> int:
args = _parse_args()
operator_addr = os.environ.get("HACKATHON_WALLET_ADDRESS")
if not operator_addr:
logger.error("HACKATHON_WALLET_ADDRESS not set")
return 2
grantee = args.grantee or operator_addr
grantee = Web3.to_checksum_address(grantee)
operator_addr = Web3.to_checksum_address(operator_addr)
client = OnChainClient()
owner = Web3.to_checksum_address(
client.reputation.functions.owner().call()
)
logger.info(
"ReputationRegistry @ %s — owner=%s, operator=%s, grantee=%s",
client.config.reputation_registry,
owner,
operator_addr,
grantee,
)
if owner != operator_addr:
logger.error(
"operator wallet is NOT the contract owner; setAuthorized "
"would revert. Owner=%s, operator=%s",
owner,
operator_addr,
)
return 3
already = await is_authorized(grantee)
if already and not args.revoke:
logger.info(
"grantee %s is already authorized (owner-implicit or explicit); "
"skipping setAuthorized",
grantee,
)
return 0
if (not already) and args.revoke:
logger.info(
"grantee %s is not currently authorized; nothing to revoke",
grantee,
)
return 0
desired = not args.revoke
logger.info(
"sending setAuthorized(%s, %s)…", grantee, desired
)
tx_hash = await set_authorized(grantee, desired)
logger.info("setAuthorized tx=%s", tx_hash)
# Confirm new state.
new_state = await is_authorized(grantee)
logger.info(
"post-tx authorized[%s] = %s (expected %s)",
grantee,
new_state,
desired,
)
if bool(new_state) != bool(desired):
logger.error("authorization state did not flip — check tx receipt")
return 4
return 0
if __name__ == "__main__":
sys.exit(asyncio.run(main()))