Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions contracts/AGIJobManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -702,8 +702,9 @@ contract AGIJobManager is Ownable, ReentrancyGuard, Pausable, ERC721 {
function updateAGITokenAddress(address _newTokenAddress) external onlyOwner whenIdentityConfigurable {
if (_newTokenAddress == address(0)) revert InvalidParameters();
_requireEmptyEscrow();
emit AGITokenAddressUpdated(address(agiToken), _newTokenAddress);
address oldToken = address(agiToken);
agiToken = IERC20(_newTokenAddress);
emit AGITokenAddressUpdated(oldToken, _newTokenAddress);
}
function updateEnsRegistry(address _newEnsRegistry) external onlyOwner whenIdentityConfigurable {
if (_newEnsRegistry == address(0)) revert InvalidParameters();
Expand All @@ -719,12 +720,14 @@ contract AGIJobManager is Ownable, ReentrancyGuard, Pausable, ERC721 {
}
function setEnsJobPages(address _ensJobPages) external onlyOwner whenIdentityConfigurable {
if (_ensJobPages != address(0) && _ensJobPages.code.length == 0) revert InvalidParameters();
emit EnsJobPagesUpdated(ensJobPages, _ensJobPages);
address oldEnsJobPages = ensJobPages;
ensJobPages = _ensJobPages;
emit EnsJobPagesUpdated(oldEnsJobPages, _ensJobPages);
}
function setUseEnsJobTokenURI(bool enabled) external onlyOwner {
emit UseEnsJobTokenURIUpdated(useEnsJobTokenURI, enabled);
bool oldValue = useEnsJobTokenURI;
useEnsJobTokenURI = enabled;
emit UseEnsJobTokenURIUpdated(oldValue, enabled);
}
function updateRootNodes(
bytes32 _clubRootNode,
Expand All @@ -747,18 +750,21 @@ contract AGIJobManager is Ownable, ReentrancyGuard, Pausable, ERC721 {
function setBaseIpfsUrl(string calldata _url) external onlyOwner { baseIpfsUrl = _url; }
function setRequiredValidatorApprovals(uint256 _approvals) external onlyOwner {
_validateValidatorThresholds(_approvals, requiredValidatorDisapprovals);
emit RequiredValidatorApprovalsUpdated(requiredValidatorApprovals, _approvals);
uint256 oldApprovals = requiredValidatorApprovals;
requiredValidatorApprovals = _approvals;
emit RequiredValidatorApprovalsUpdated(oldApprovals, _approvals);
}
function setRequiredValidatorDisapprovals(uint256 _disapprovals) external onlyOwner {
_validateValidatorThresholds(requiredValidatorApprovals, _disapprovals);
emit RequiredValidatorDisapprovalsUpdated(requiredValidatorDisapprovals, _disapprovals);
uint256 oldDisapprovals = requiredValidatorDisapprovals;
requiredValidatorDisapprovals = _disapprovals;
emit RequiredValidatorDisapprovalsUpdated(oldDisapprovals, _disapprovals);
}
function setVoteQuorum(uint256 _quorum) external onlyOwner {
if (_quorum == 0 || _quorum > MAX_VALIDATORS_PER_JOB) revert InvalidParameters();
emit VoteQuorumUpdated(voteQuorum, _quorum);
uint256 oldQuorum = voteQuorum;
voteQuorum = _quorum;
emit VoteQuorumUpdated(oldQuorum, _quorum);
}
function setPremiumReputationThreshold(uint256 _threshold) external onlyOwner { premiumReputationThreshold = _threshold; }
function setMaxJobPayout(uint256 _maxPayout) external onlyOwner { maxJobPayout = _maxPayout; }
Expand Down Expand Up @@ -791,27 +797,32 @@ contract AGIJobManager is Ownable, ReentrancyGuard, Pausable, ERC721 {
function setAgentBondParams(uint256 bps, uint256 min, uint256 max) external onlyOwner {
if (bps > 10_000) revert InvalidParameters();
if (min > max) revert InvalidParameters();
uint256 oldBps = agentBondBps;
uint256 oldMin = agentBond;
uint256 oldMax = agentBondMax;
if (bps == 0 && min == 0 && max == 0) {
emit AgentBondParamsUpdated(agentBondBps, agentBond, agentBondMax, 0, 0, 0);
agentBondBps = 0;
agentBond = 0;
agentBondMax = 0;
emit AgentBondParamsUpdated(oldBps, oldMin, oldMax, 0, 0, 0);
return;
}
if (max == 0) revert InvalidParameters();
emit AgentBondParamsUpdated(agentBondBps, agentBond, agentBondMax, bps, min, max);
agentBondBps = bps;
agentBond = min;
agentBondMax = max;
emit AgentBondParamsUpdated(oldBps, oldMin, oldMax, bps, min, max);
}
function setAgentBond(uint256 bond) external onlyOwner {
emit AgentBondMinUpdated(agentBond, bond);
uint256 oldMin = agentBond;
agentBond = bond;
emit AgentBondMinUpdated(oldMin, bond);
}
function setValidatorSlashBps(uint256 bps) external onlyOwner {
if (bps > 10_000) revert InvalidParameters();
emit ValidatorSlashBpsUpdated(validatorSlashBps, bps);
uint256 oldBps = validatorSlashBps;
validatorSlashBps = bps;
emit ValidatorSlashBpsUpdated(oldBps, bps);
}
function setChallengePeriodAfterApproval(uint256 period) external onlyOwner {
_requireValidReviewPeriod(period);
Expand Down Expand Up @@ -893,8 +904,9 @@ contract AGIJobManager is Ownable, ReentrancyGuard, Pausable, ERC721 {
if (!(_percentage > 0 && _percentage <= 100)) revert InvalidParameters();
uint256 maxPct = _maxAGITypePayoutPercentage();
if (maxPct > 100 - _percentage) revert InvalidParameters();
emit ValidationRewardPercentageUpdated(validationRewardPercentage, _percentage);
uint256 oldPercentage = validationRewardPercentage;
validationRewardPercentage = _percentage;
emit ValidationRewardPercentageUpdated(oldPercentage, _percentage);
}

function enforceReputationGrowth(address _user, uint256 _points) internal {
Expand Down
2 changes: 1 addition & 1 deletion docs/operator-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ safe day‑to‑day operations, emergency procedures, and monitoring.
**Use when**: incident response, parameter change review, treasury withdrawal.

- `pause()` blocks new activity (create/apply/vote/dispute/reward pool contribution) but preserves settlement exits.
- `setSettlementPaused(true)` freezes settlement/exit paths (`cancelJob`, `expireJob`, `finalizeJob`, `delistJob`) guarded by `whenSettlementNotPaused`.
- `setSettlementPaused(true)` freezes settlement/exit paths (`cancelJob`, `expireJob`, `finalizeJob`, `delistJob`, `resolveDispute*`, `resolveStaleDispute`, `withdrawAGI`) guarded by `whenSettlementNotPaused`.
- **Incident sequence:** call `setSettlementPaused(true)` first to stop fund-out, then `pause()` to stop intake.
- **Recovery:** unpause intake only after settlement is safe; keep `settlementPaused` on until final safety, then set it to false last.

Expand Down
3 changes: 2 additions & 1 deletion docs/ops/parameter-safety.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ This document is a production-grade **operator checklist** for preventing and re
| `disputeReviewPeriod` (`setDisputeReviewPeriod`) | seconds | Window before `resolveStaleDispute` is allowed (owner‑only; pausing optional for incident recovery). | `1..365 days` | Days to weeks (7d–30d) to give moderators time to resolve. | Too short → owner can settle too early in incidents; too long → disputes can deadlock. | Adjust window; maintain moderator redundancy. |
| `premiumReputationThreshold` (`setPremiumReputationThreshold`) | points | `canAccessPremiumFeature`. | Any non-negative uint. | Mis-set only affects premium access (no settlement impact). | Adjust threshold. |
| `AGIType.payoutPercentage` (`addAGIType`) | uint256 percentage | Agent payout percentage in `_completeJob`. | `1..100`; **highest** payout across AGI types must satisfy `maxAgentPayoutPercentage + validationRewardPercentage <= 100` (enforced). | If any agent holds a high-percentage NFT that pushes the sum > 100, completion can revert. | Lower AGI type percentage (or validation reward %); re-validate. |
| `pause` / `unpause` | bool | Gates most job actions. | Use `pause` for incident response, not normal ops. | If paused, new activity reverts (create/apply/validate/dispute). Completion requests and settlement exits can still proceed. | Unpause after fixing parameters; no funds lost. |
| `pause` / `unpause` | bool | **Intake pause** for most job actions. | Use `pause` for incident response, not normal ops. | If paused, new activity reverts (create/apply/validate/dispute/reward pool). Completion requests and settlement exits can still proceed. | Unpause after fixing parameters; no funds lost. |
| `settlementPaused` (`setSettlementPaused`) | bool | **Emergency settlement freeze** for fund-out paths. | Use first in incidents to freeze settlement while preserving intake pause choice. | If set, settlement exits revert (`cancelJob`, `expireJob`, `finalizeJob`, `delistJob`, `resolveDispute*`, `resolveStaleDispute`, `withdrawAGI`). | Clear only after settlement math/invariants are safe; then unpause intake last if desired. |
| `addAdditionalAgent` / `addAdditionalValidator` | allowlist | Eligibility bypass. | Only use for emergency recovery or vetted identities. | Overuse weakens gating; underuse when Merkle/ENS config is wrong can stall jobs. | Add temporary allowlist entries; remove later. |
| `blacklistedAgents` / `blacklistedValidators` | bool | Eligibility gating. | Use sparingly with documented reasons. | If critical participants are blacklisted, jobs cannot progress (validate/apply revert). | Un-blacklist or resolve by moderator. |
| `addModerator` / `removeModerator` | address | Dispute resolution authority. | Ensure ≥1 active moderator. | If no moderator exists, disputes can’t resolve → funds stuck. | Add a moderator (owner action). |
Expand Down