-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
- [x] Add RegistryManager contract - [x] Add EASRegistryManager contract - [x] Add Common contract with common errors - [x] Minor refactoring - [x] Add tests
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
name: Slither Analysis | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
slither: | ||
runs-on: ubuntu-22.04 | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: pnpm/action-setup@v4 | ||
with: | ||
version: 9 | ||
|
||
- name: Use Node.js 20 | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: 20 | ||
cache: "pnpm" | ||
|
||
- name: Install | ||
run: | | ||
pnpm install --frozen-lockfile --prefer-offline | ||
- name: Build | ||
run: | | ||
pnpm run build | ||
working-directory: packages/contracts | ||
|
||
- name: Run Slither | ||
uses: crytic/[email protected] | ||
continue-on-error: true | ||
id: slither | ||
with: | ||
sarif: results.sarif | ||
fail-on: none | ||
ignore-compile: true | ||
node-version: 20 | ||
target: "packages/contracts/" | ||
|
||
- name: Upload SARIF file | ||
uses: github/codeql-action/upload-sarif@v3 | ||
with: | ||
sarif_file: ${{ steps.slither.outputs.sarif }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
/// @title Common | ||
/// @notice Contract that contains common things for all the contracts | ||
contract Common { | ||
/// @notice custom errors | ||
error InvalidAddress(); | ||
error InvalidInput(); | ||
error InvalidIndex(); | ||
error ValidationError(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { IRecipientRegistry } from "./IRecipientRegistry.sol"; | ||
|
||
/// @title IRegistryManager | ||
/// @notice An interface for a registry manager. Allows to manage requests for Registry. | ||
interface IRegistryManager { | ||
/// @notice Enum representing request type | ||
enum RequestType { | ||
Add, | ||
Change | ||
} | ||
|
||
/// @notice Enum representing request status | ||
enum Status { | ||
Pending, | ||
Approved, | ||
Rejected | ||
} | ||
|
||
/// @notice Request data | ||
struct Request { | ||
/// @notice index (optional) | ||
uint256 index; | ||
/// @notice registry address | ||
address registry; | ||
/// @notice request type | ||
RequestType requestType; | ||
/// @notice recipient data | ||
IRecipientRegistry.Recipient recipient; | ||
} | ||
|
||
/// @notice Events | ||
event RequestSent( | ||
address indexed registry, | ||
RequestType indexed requestType, | ||
address indexed recipient, | ||
uint256 index, | ||
bytes32 id, | ||
bytes32 metadataUrl | ||
); | ||
event RequestApproved( | ||
address indexed registry, | ||
RequestType indexed requestType, | ||
address indexed recipient, | ||
uint256 index, | ||
bytes32 id, | ||
bytes32 metadataUrl | ||
); | ||
event RequestRejected( | ||
address indexed registry, | ||
RequestType indexed requestType, | ||
address indexed recipient, | ||
uint256 index, | ||
bytes32 id, | ||
bytes32 metadataUrl | ||
); | ||
|
||
/// @notice Custom errors | ||
error OperationError(); | ||
|
||
/// @notice Send the request to the Registry | ||
/// @param request user request | ||
function send(Request calldata request) external; | ||
|
||
/// @notice Approve the request and call registry function | ||
/// @param index The index of the request | ||
function approve(uint256 index) external; | ||
|
||
/// @notice Reject the request | ||
/// @param index The index of the request | ||
function reject(uint256 index) external; | ||
|
||
/// @notice Get a request | ||
/// @param index The index of the request | ||
/// @return request The request with index and data | ||
/// @return status The request status | ||
function getRequest(uint256 index) external view returns (Request memory request, Status status); | ||
|
||
/// @notice Get the number of requests | ||
/// @return The number of requests | ||
function requestCount() external view returns (uint256); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { BaseRegistry } from "../registry/BaseRegistry.sol"; | ||
|
||
/// @title MockRegistry | ||
/// @notice Mock registry contract | ||
contract MockRegistry is BaseRegistry { | ||
/// @notice Create a new instance of the registry contract | ||
/// @param maxRecipients The maximum number of projects that can be registered | ||
/// @param metadataUrl The metadata url | ||
constructor(uint256 maxRecipients, bytes32 metadataUrl) payable BaseRegistry(maxRecipients, metadataUrl) {} | ||
Check notice Code scanning / Slither Local variable shadowing Low
MockRegistry.constructor(uint256,bytes32).metadataUrl shadows:
- BaseRegistry.metadataUrl (state variable) Check notice Code scanning / Slither Local variable shadowing Low
MockRegistry.constructor(uint256,bytes32).maxRecipients shadows:
- BaseRegistry.maxRecipients (state variable) - IRecipientRegistry.maxRecipients() (function) |
||
} | ||
Check warning Code scanning / Slither Contracts that lock Ether Medium
Contract locking ether found:
Contract MockRegistry has payable functions: - BaseRegistry.constructor(uint256,bytes32) - MockRegistry.constructor(uint256,bytes32) But does not have a function to withdraw the ether |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,20 +6,26 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; | |
import { IEAS } from "../interfaces/IEAS.sol"; | ||
import { BaseRegistry } from "./BaseRegistry.sol"; | ||
|
||
/// @title EASRegistry | ||
/// @notice EAS registry contract | ||
contract EASRegistry is Ownable, BaseRegistry, IEAS { | ||
/// @notice The EAS contract | ||
IEAS public immutable eas; | ||
|
||
/// @notice Create a new instance of the registry contract | ||
/// @param _maxRecipients The maximum number of projects that can be registered | ||
/// @param _metadataUrl The metadata url | ||
/// @param _eas The EAS address | ||
/// @param maxRecipients The maximum number of projects that can be registered | ||
/// @param metadataUrl The metadata url | ||
/// @param easAddress The EAS address | ||
constructor( | ||
uint256 _maxRecipients, | ||
bytes32 _metadataUrl, | ||
address _eas | ||
) payable Ownable(msg.sender) BaseRegistry(_maxRecipients, _metadataUrl) { | ||
eas = IEAS(_eas); | ||
uint256 maxRecipients, | ||
Check notice Code scanning / Slither Local variable shadowing Low
EASRegistry.constructor(uint256,bytes32,address).maxRecipients shadows:
- BaseRegistry.maxRecipients (state variable) - IRecipientRegistry.maxRecipients() (function) |
||
bytes32 metadataUrl, | ||
Check notice Code scanning / Slither Local variable shadowing Low
EASRegistry.constructor(uint256,bytes32,address).metadataUrl shadows:
- BaseRegistry.metadataUrl (state variable) |
||
address easAddress | ||
) payable Ownable(msg.sender) BaseRegistry(maxRecipients, metadataUrl) { | ||
if (easAddress == address(0)) { | ||
revert InvalidAddress(); | ||
} | ||
|
||
eas = IEAS(easAddress); | ||
} | ||
|
||
/// @notice Add multiple recipients to the registry | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { IEAS } from "../interfaces/IEAS.sol"; | ||
import { IRecipientRegistry } from "../interfaces/IRecipientRegistry.sol"; | ||
import { RegistryManager } from "./RegistryManager.sol"; | ||
|
||
/// @title EASRegistryManager | ||
/// @notice Contract that allows to use send, approve, reject requests to EASRegistry. | ||
contract EASRegistryManager is RegistryManager { | ||
/// @notice custom errors | ||
error NotYourAttestation(); | ||
|
||
/// @notice EAS | ||
IEAS public eas; | ||
Check warning Code scanning / Slither State variables that could be declared immutable Warning
EASRegistryManager.eas should be immutable
|
||
|
||
/// @notice Initialize EASRegistryManager | ||
/// @param easAddress EAS contract address | ||
constructor(address easAddress) payable { | ||
if (easAddress == address(0)) { | ||
revert InvalidAddress(); | ||
} | ||
|
||
eas = IEAS(easAddress); | ||
} | ||
|
||
/// @notice Check recipient has an EAS attestation | ||
/// @param request request to the registry | ||
modifier onlyWithAttestation(Request memory request) { | ||
if (request.requestType != RequestType.Change) { | ||
_; | ||
return; | ||
} | ||
|
||
IEAS.Attestation memory attestation = eas.getAttestation(request.recipient.id); | ||
|
||
if (attestation.recipient != request.recipient.recipient) { | ||
revert NotYourAttestation(); | ||
} | ||
|
||
_; | ||
} | ||
|
||
/// @inheritdoc RegistryManager | ||
function send( | ||
Request calldata request | ||
) public virtual override isValidRequest(request) onlyWithAttestation(request) { | ||
super.send(request); | ||
} | ||
} | ||
Check warning Code scanning / Slither Contracts that lock Ether Medium
Contract locking ether found:
Contract EASRegistryManager has payable functions: - RegistryManager.constructor() - EASRegistryManager.constructor(address) But does not have a function to withdraw the ether |