Skip to content

Commit

Permalink
Slash Proposals (#108)
Browse files Browse the repository at this point in the history
* added state machine contract

* state machine same states for all machines

* SlashingController initial commit

* Configurable slash reasons, in review states and proposal editing.

* deploying SlashingController

* fix state machine creation

* - Added stake freezing side effects to SlashingController
- Proposing slash checks for subject existence, unified interface isRegistered in AgentRegistry
- Fixed typos in docs (XXXRegistry reference to ERC1155 should be ERC721)

* WIP: slashing calculations

* test slashing amounts

* evidence handling

* added tests and comments

* fix onlyInState and natspec StateMachines

* SlashController: change frozen stake when reviewing proposal, fix events, tests

* SlashController: modify proposal tests, no need to check for proposal existance there

* SlashController: fix wrong next states size, removed unnecesary checks, reused error message MissingRole, tests

* FortaStaking: comments

* FortaStakingParameters: comments

* SlashingController: implements ISlashingController

* linting

* FortaStaking: make stake to shares converters public

* SlashController: removed MAX_STAKE penalty mode, since it will always be the max possible stake

* fix tests

* Update contracts/components/staking/SlashingController.sol

Co-authored-by: Hadrien Croubois <[email protected]>

* Update contracts/components/staking/SlashingController.sol

reentrancy fix returning deposit

Co-authored-by: Hadrien Croubois <[email protected]>

* Update contracts/components/staking/SlashingController.sol

reentrancy protection on slash deposit

Co-authored-by: Hadrien Croubois <[email protected]>

* SlashingController: msg.sender -> _msgSender(), fix role check for revert proposal

* SlashingController: immutable depositToken

* SlashingController: max string length for evidence

* StateMachines & SlashingController: refactor to more efficient state machines

* StateMachines attribution

* SlashingController and FortaStaking: reverted to accessControl SLASHER_ROLE for slash and freeze

* SlashingController: move _transition up in markAsInReviewSlashProposal

Co-authored-by: Hadrien Croubois <[email protected]>
  • Loading branch information
Ramarti and Amxx authored Aug 29, 2022
1 parent 064601d commit c940dc3
Show file tree
Hide file tree
Showing 28 changed files with 1,579 additions and 182 deletions.
2 changes: 1 addition & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error",
"max-line-length": ["error", 180],
"max-line-length": ["error", 150],
"func-param-name-mixedcase": "error",
"modifier-name-mixedcase": "error",
"private-vars-leading-underscore": "error",
Expand Down
5 changes: 4 additions & 1 deletion contracts/components/Roles.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ bytes32 constant DISPATCHER_ROLE = keccak256("DISPATCHER_ROLE");
// Staking
bytes32 constant SLASHER_ROLE = keccak256("SLASHER_ROLE");
bytes32 constant SWEEPER_ROLE = keccak256("SWEEPER_ROLE");
bytes32 constant REWARDS_ADMIN = keccak256("REWARDS_ADMIN_ROLE");
bytes32 constant REWARDS_ADMIN_ROLE = keccak256("REWARDS_ADMIN_ROLE");
bytes32 constant SLASHING_ARBITER_ROLE = keccak256("SLASHING_ARBITER_ROLE");
bytes32 constant STAKING_ADMIN_ROLE = keccak256("STAKING_ADMIN_ROLE");

// Scanner Node Version
bytes32 constant SCANNER_VERSION_ROLE = keccak256("SCANNER_VERSION_ROLE");
bytes32 constant SCANNER_BETA_VERSION_ROLE = keccak256("SCANNER_BETA_VERSION_ROLE");
16 changes: 8 additions & 8 deletions contracts/components/agents/AgentRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ contract AgentRegistry is
AgentRegistryMetadata,
AgentRegistryEnumerable
{
string public constant version = "0.1.3";
string public constant version = "0.1.4";
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address forwarder) initializer ForwardedContext(forwarder) {}

/**
* @notice Initializer method, access point to initialize inheritance tree.
* @param __manager address of AccessManager.
* @param __router address of Router.
* @param __name ERC1155 token name.
* @param __symbol ERC1155 token symbol.
* @param __name ERC721 token name.
* @param __symbol ERC721 token symbol.
*/
function initialize(
address __manager,
Expand All @@ -42,8 +42,8 @@ contract AgentRegistry is

/**
* @notice Gets all Agent state.
* @param agentId ERC1155 token id of the agent.
* @return created if agent exists.
* @param agentId ERC721 token id of the agent.
* @return registered if agent exists.
* @return owner address.
* @return agentVersion of the agent.
* @return metadata IPFS pointer.
Expand All @@ -54,17 +54,17 @@ contract AgentRegistry is
function getAgentState(uint256 agentId)
public view
returns (
bool created,
bool registered,
address owner,
uint256 agentVersion,
string memory metadata,
uint256[] memory chainIds,
bool enabled,
uint256 disabledFlags
) {
(created, owner, agentVersion, metadata, chainIds) = getAgent(agentId);
(registered, owner, agentVersion, metadata, chainIds) = getAgent(agentId);
return (
created,
registered,
owner,
agentVersion,
metadata,
Expand Down
18 changes: 9 additions & 9 deletions contracts/components/agents/AgentRegistryCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ abstract contract AgentRegistryCore is

/**
* @notice Checks sender (or metatx signer) is owner of the agent token.
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
*/
modifier onlyOwnerOf(uint256 agentId) {
if (_msgSender() != ownerOf(agentId)) revert SenderNotOwner(_msgSender(), agentId);
Expand Down Expand Up @@ -56,11 +56,11 @@ abstract contract AgentRegistryCore is
}

/**
* @notice Agent creation method. Mints an ERC1155 token with the agent id for the owner and stores metadata.
* @notice Agent creation method. Mints an ERC721 token with the agent id for the owner and stores metadata.
* @dev fires _before and _after hooks within the inheritance tree.
* If front run protection is enabled (disabled by default), it will check if the keccak256 hash of the parameters
* has been committed in prepareAgent(bytes32).
* @param agentId ERC1155 token id of the agent to be created.
* @param agentId ERC721 token id of the agent to be created.
* @param owner address to have ownership privileges in the agent methods.
* @param metadata IPFS pointer to agent's metadata JSON.
* @param chainIds ordered list of chainIds where the agent wants to run.
Expand All @@ -78,17 +78,17 @@ abstract contract AgentRegistryCore is

/**
* @notice Checks if the agentId has been minted.
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @return true if agentId exists, false otherwise.
*/
function isCreated(uint256 agentId) public view returns(bool) {
function isRegistered(uint256 agentId) public view returns(bool) {
return _exists(agentId);
}

/**
* @notice Updates parameters of an agentId (metadata, image, chain IDs...) if called by the agent owner.
* @dev fires _before and _after hooks within the inheritance tree.
* @param agentId ERC1155 token id of the agent to be updated.
* @param agentId ERC721 token id of the agent to be updated.
* @param metadata IPFS pointer to agent's metadata JSON.
* @param chainIds ordered list of chainIds where the agent wants to run.
*/
Expand Down Expand Up @@ -143,7 +143,7 @@ abstract contract AgentRegistryCore is
/**
* @notice hook fired before agent creation or update.
* @dev does nothing in this contract.
* @param agentId ERC1155 token id of the agent to be created or updated.
* @param agentId ERC721 token id of the agent to be created or updated.
* @param newMetadata IPFS pointer to agent's metadata JSON.
* @param newChainIds ordered list of chainIds where the agent wants to run.
*/
Expand All @@ -153,7 +153,7 @@ abstract contract AgentRegistryCore is
/**
* @notice logic for agent update.
* @dev emits AgentUpdated, will be extended by child contracts.
* @param agentId ERC1155 token id of the agent to be created or updated.
* @param agentId ERC721 token id of the agent to be created or updated.
* @param newMetadata IPFS pointer to agent's metadata JSON.
* @param newChainIds ordered list of chainIds where the agent wants to run.
*/
Expand All @@ -164,7 +164,7 @@ abstract contract AgentRegistryCore is
/**
* @notice hook fired after agent creation or update.
* @dev emits Router hook.
* @param agentId ERC1155 token id of the agent to be created or updated.
* @param agentId ERC721 token id of the agent to be created or updated.
* @param newMetadata IPFS pointer to agent's metadata JSON.
* @param newChainIds ordered list of chainIds where the agent wants to run.
*/
Expand Down
20 changes: 10 additions & 10 deletions contracts/components/agents/AgentRegistryEnable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {

/**
* @notice Check if agent is enabled
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @return true if the agent exist, has not been disabled, and is staked over minimum
* Returns false if otherwise
*/
function isEnabled(uint256 agentId) public view virtual returns (bool) {
return isCreated(agentId) &&
return isRegistered(agentId) &&
getDisableFlags(agentId) == 0 &&
_isStakedOverMin(agentId);
}

/**
* @notice Enable an agent if sender has correct permission and the agent is staked over minimum stake.
* @dev agents can be disabled by ADMIN or OWNER.
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @param permission the sender claims to have to enable the agent.
*/
function enableAgent(uint256 agentId, Permission permission) public virtual {
Expand All @@ -52,7 +52,7 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {
/**
* @notice Disable an agent if sender has correct permission.
* @dev agents can be disabled by ADMIN or OWNER.
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @param permission the sender claims to have to enable the agent.
*/
function disableAgent(uint256 agentId, Permission permission) public virtual {
Expand All @@ -64,7 +64,7 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {
* @notice Get the disabled flags for an agentId.
* @dev Permission (uint8) is used for indexing, so we don't need to loop.
* If not disabled, all flags will be 0.
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @return uint256 containing the byte flags.
*/
function getDisableFlags(uint256 agentId) public view returns (uint256) {
Expand All @@ -74,7 +74,7 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {
/**
* @notice Permission check.
* @dev it does not uses AccessManager since it is agent specific
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @param permission the sender claims to have to enable the agent.
* @return true if: permission.ADMIN and _msgSender is ADMIN_ROLE, Permission.OWNER and owner of agentId,
* false otherwise.
Expand All @@ -88,7 +88,7 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {
/**
* @notice Internal methods for enabling the agent.
* @dev fires hook _before and _after enable within the inheritance tree.
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @param permission the sender claims to have to enable the agent.
* @param enable true if enabling, false if disabling.
*/
Expand All @@ -101,7 +101,7 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {
/**
* @notice Hook _before agent enable
* @dev does nothing in this contract
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @param permission the sender claims to have to enable the agent.
* @param value true if enabling, false if disabling.
*/
Expand All @@ -111,7 +111,7 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {
/**
* @notice Logic for enabling agents, sets flag corresponding to permission.
* @dev does nothing in this contract
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @param permission the sender claims to have to enable the agent.
* @param value true if enabling, false if disabling.
*/
Expand All @@ -123,7 +123,7 @@ abstract contract AgentRegistryEnable is AgentRegistryCore {
/**
* @notice Hook _after agent enable
* @dev emits Router hook
* @param agentId ERC1155 token id of the agent.
* @param agentId ERC721 token id of the agent.
* @param permission the sender claims to have to enable the agent.
* @param value true if enabling, false if disabling.
*/
Expand Down
2 changes: 1 addition & 1 deletion contracts/components/agents/AgentRegistryEnumerable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ abstract contract AgentRegistryEnumerable is AgentRegistryMetadata {
/**
* @notice hook fired before agent creation or update.
* @dev stores agent in _allAgents if it wasn't there, manages agent arrays by chain.
* @param agentId ERC1155 token id of the agent to be created or updated.
* @param agentId ERC721 token id of the agent to be created or updated.
* @param newMetadata IPFS pointer to agent's metadata JSON.
* @param newChainIds ordered list of chainIds where the agent wants to run.
*/
Expand Down
8 changes: 4 additions & 4 deletions contracts/components/agents/AgentRegistryMetadata.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ abstract contract AgentRegistryMetadata is AgentRegistryCore {

/**
* @notice Gets agent metadata, version and chain Ids.
* @param agentId ERC1155 token id of the agent.
* @return created if agent exists.
* @param agentId ERC721 token id of the agent.
* @return registered if agent exists.
* @return owner address.
* @return agentVersion of the agent.
* @return metadata IPFS pointer.
* @return chainIds the agent wants to run in.
*/
function getAgent(uint256 agentId)
public view
returns (bool created, address owner,uint256 agentVersion, string memory metadata, uint256[] memory chainIds) {
returns (bool registered, address owner,uint256 agentVersion, string memory metadata, uint256[] memory chainIds) {
bool exists = _exists(agentId);
return (
exists,
Expand All @@ -42,7 +42,7 @@ abstract contract AgentRegistryMetadata is AgentRegistryCore {
/**
* @notice logic for agent update.
* @dev checks metadata uniqueness and updates agent metadata and version.
* @param agentId ERC1155 token id of the agent to be created or updated.
* @param agentId ERC721 token id of the agent to be created or updated.
* @param newMetadata IPFS pointer to agent's metadata JSON.
* @param newChainIds ordered list of chainIds where the agent wants to run.
*/
Expand Down
4 changes: 2 additions & 2 deletions contracts/components/dispatch/Dispatch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ contract Dispatch is BaseComponentUpgradeable {
AgentRegistry private _agents;
ScannerRegistry private _scanners;

string public constant version = "0.1.4";
string public constant version = "0.1.5";

mapping(uint256 => EnumerableSet.UintSet) private scannerToAgents;
mapping(uint256 => EnumerableSet.UintSet) private agentToScanners;
Expand Down Expand Up @@ -197,7 +197,7 @@ contract Dispatch is BaseComponentUpgradeable {
* @param scannerId ERC1155 token id of the scanner.
*/
function unlink(uint256 agentId, uint256 scannerId) public onlyRole(DISPATCHER_ROLE) {
if (!_agents.isCreated(agentId)) revert InvalidId("Agent", agentId);
if (!_agents.isRegistered(agentId)) revert InvalidId("Agent", agentId);
if (!_scanners.isRegistered(scannerId)) revert InvalidId("Scanner", scannerId);

if (!scannerToAgents[scannerId].remove(agentId) || !agentToScanners[agentId].remove(scannerId)) {
Expand Down
6 changes: 3 additions & 3 deletions contracts/components/scanners/ScannerRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ contract ScannerRegistry is
* @notice Initializer method, access point to initialize inheritance tree.
* @param __manager address of AccessManager.
* @param __router address of Router.
* @param __name ERC1155 token name.
* @param __symbol ERC1155 token symbol.
* @param __name ERC721 token name.
* @param __symbol ERC721 token symbol.
*/
function initialize(
address __manager,
Expand All @@ -41,7 +41,7 @@ contract ScannerRegistry is

/**
* @notice Gets all scanner properties and state
* @param scannerId ERC1155 token id of the scanner.
* @param scannerId ERC721 token id of the scanner.
* @return registered true if scanner exists.
* @return owner address.
* @return chainId the scanner is monitoring.
Expand Down
22 changes: 11 additions & 11 deletions contracts/components/scanners/ScannerRegistryCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ abstract contract ScannerRegistryCore is

/**
* @notice Checks sender (or metatx signer) is owner of the scanner token.
* @param scannerId ERC1155 token id of the scanner.
* @param scannerId ERC721 token id of the scanner.
*/
modifier onlyOwnerOf(uint256 scannerId) {
if (_msgSender() != ownerOf(scannerId)) revert SenderNotOwner(_msgSender(), scannerId);
Expand All @@ -33,7 +33,7 @@ abstract contract ScannerRegistryCore is

/**
* @notice Scanner registration via admin key.
* @dev restricted to SCANNER_ADMIN_ROLE. Scanner address will be converted to uin256 ERC1155 token id.
* @dev restricted to SCANNER_ADMIN_ROLE. Scanner address will be converted to uin256 ERC721 token id.
* @param scanner address generated by scanner software.
* @param owner of the scanner. Will have admin privileges over the registering scanner.
* @param chainId that the scanner will monitor.
Expand All @@ -45,15 +45,15 @@ abstract contract ScannerRegistryCore is

/**
* @notice Checks if scannerId has been registered (minted).
* @param scannerId ERC1155 token id of the scanner.
* @param scannerId ERC721 token id of the scanner.
* @return true if scannerId exists, false otherwise.
*/
function isRegistered(uint256 scannerId) public view returns(bool) {
function isRegistered(uint256 scannerId) public view override returns(bool) {
return _exists(scannerId);
}

/**
* @notice Public method for scanners to self register in Forta and mint registration ERC1155 token.
* @notice Public method for scanners to self register in Forta and mint registration ERC721 token.
* @dev _msgSender() will be considered the Scanner Node address.
* @param owner of the scanner. Will have admin privileges over the registering scanner.
* @param chainId that the scanner will monitor.
Expand All @@ -65,9 +65,9 @@ abstract contract ScannerRegistryCore is
}

/**
* @notice Internal method for scanners to self register in Forta and mint registration ERC1155 token.
* @notice Internal method for scanners to self register in Forta and mint registration ERC721 token.
* Public staking must be activated in the target chainId.
* @dev Scanner address will be converted to uin256 ERC1155 token id. Will trigger _before and _after hooks within
* @dev Scanner address will be converted to uin256 ERC721 token id. Will trigger _before and _after hooks within
* the inheritance tree.
* @param owner of the scanner. Will have admin privileges over the registering scanner.
* @param chainId that the scanner will monitor.
Expand Down Expand Up @@ -97,7 +97,7 @@ abstract contract ScannerRegistryCore is
_afterScannerUpdate(scannerId, chainId, metadata);
}

/// Converts scanner address to uint256 for ERC1155 Token Id.
/// Converts scanner address to uint256 for ERC721 Token Id.
function scannerAddressToId(address scanner) public pure returns(uint256) {
return uint256(uint160(scanner));
}
Expand Down Expand Up @@ -143,7 +143,7 @@ abstract contract ScannerRegistryCore is
/**
* @notice _before hook triggered before scanner creation or update.
* @dev Does nothing in this base contract.
* @param scannerId ERC1155 token id of the scanner.
* @param scannerId ERC721 token id of the scanner.
* @param chainId that the scanner will monitor.
* @param metadata IPFS pointer to scanner's metadata JSON
*/
Expand All @@ -153,7 +153,7 @@ abstract contract ScannerRegistryCore is
/**
* @notice Scanner update logic.
* @dev Emits ScannerUpdated(scannerId, chainId, metadata)
* @param scannerId ERC1155 token id of the scanner.
* @param scannerId ERC721 token id of the scanner.
* @param chainId that the scanner will monitor.
* @param metadata IPFS pointer to scanner's metadata JSON
*/
Expand All @@ -164,7 +164,7 @@ abstract contract ScannerRegistryCore is
/**
* @notice _after hook triggered after scanner creation or update.
* @dev emits Router hook
* @param scannerId ERC1155 token id of the scanner.
* @param scannerId ERC721 token id of the scanner.
* @param chainId that the scanner will monitor.
* @param metadata IPFS pointer to scanner's metadata JSON
*/
Expand Down
Loading

0 comments on commit c940dc3

Please sign in to comment.