Skip to content

Commit

Permalink
Improve README (#55)
Browse files Browse the repository at this point in the history
* [#45] Add hardhat task to generate markdown file of deployed contract addresses

* [#45] Use table in README--md for other commands, open links in new tab in

* [#45] Add mermaid chart in README, add info about implemented components

* [#45] Add execution flows

* [#45] Add coverage number in README

* [#45] Update diagram and add usage section
  • Loading branch information
akshay-ap committed Aug 8, 2023
1 parent b50bcfd commit 0dc36e0
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 13 deletions.
119 changes: 106 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,106 @@
[![Coverage Status](https://coveralls.io/repos/github/5afe/safe-core-protocol/badge.svg)](https://coveralls.io/github/5afe/safe-core-protocol)

# Safe{Core} Protocol

This project is an implementation of [Safe{Core} Protocol specification](https://github.com/5afe/safe-protocol-specs)
## Architecture

Safe{Core} Protocol implementation consists of following main components:
- [SafeProtocolManager](./contracts/SafeProtocolManager.sol)
- [SafeProtocolRegistry](./contracts/SafeProtocolRegistry.sol)
- [Interfaces for Integrations](./contracts/interfaces/Integrations.sol)

A high level overview of the architecture is as follows:

```mermaid
graph TD
Safe -->|Execute transaction| Monitor
Safe -->|Manage Integrations| Store
Safe -->|SafeProtocolManager handling fallback functionality| FunctionHandlerSupport
PluginInstance(Plugin Instance) -->|Execute transaction from Plugin| Monitor
RegistryOwner("Registry Owner") --> Maintain
RegistryOwner("Registry Owner") --> Flag
subgraph SafeProtocolManager
Store(Maintain Enabled Integrations per Safe)
Monitor(Mediate Safe transaction execution)
FunctionHandlerSupport("Provide additional functionality using Function Handler(s)")
HooksSupport("Hooks for validating transaction execution")
Monitor -.- HooksSupport
end
subgraph SafeProtocolRegistry
AllowQuery(Provide information about Integrations)
Maintain("Maintain list of permitted Integrations")
Flag("Mark Integration as Malicious")
Monitor -...- AllowQuery
Store -...- AllowQuery
end
```

### Integrations

```mermaid
graph TD
style Integrations font-size:20px;
subgraph Integrations
Plugin(Plugin)
Hooks(Hooks)
FunctionHandler(Function Handler)
SignatureVerifier(Signature verifier)
end
```

Currently implemented components of the Safe{Core} Protocol are:
- **SafeProtocolManager**
- **SafeProtocolRegistry**
- **Plugins**
- **Hooks** for transaction execution through Plugin(s)
- Additionally a test version of registry **TestSafeProtocolRegistryUnrestricted** is also available.

[Execution flows](./docs/execution_flows.md) give a high-level overview of the different flows for the Safe{Core} Protocol.

## Deployments

All the deployed addresses of contracts are available in [deployments.ts](./deployments.ts) for each network along with contract abis. Alternatively, all the addresses are also available in a [markdown file](./docs/deployments.md)

## Using solidity interfaces

The solidity interfaces for the Safe{Core} Protocol contracts are available in [interfaces](./contracts/interfaces) directory. These interfaces are available for import into solidity smart contracts via the npm artifact.

To install the npm package, run the following command:

```bash
npm i @safe-global/safe-core-protocol
```

E.g. Create a plugin

```solidity
import {ISafeProtocolPlugin} from "@safe-global/safe-core-protocol/contracts/interfaces/Integrations.sol";
contract SamplePlugin is ISafeProtocolPlugin {
function name() external view returns (string memory name) {
...
}
function version() external view returns (string memory version){
...
}
function metadataProvider() external view returns (uint256 providerType, bytes memory location){
...
}
function requiresRootAccess() external view returns (bool requiresRootAccess){
...
}
}
```

For more examples and information on adding Integration(s) to the Registry, refer to [Safe{Core} Protocol demo](https://github.com/5afe/safe-core-protocol-demo/tree/main/contracts)

## Useful commands

Expand Down Expand Up @@ -34,17 +134,10 @@ npx hardhat test
```bash
yarn hardhat deploy --network goerli --tags protocol --export-all deployments.ts
```
### Other commands

### Verify

#### SafeProtocolRegistry.sol/TestSafeProtocolRegistryUnrestricted.sol

```
yarn hardhat verify --network goerli <contract_address> <initial_owner>
```

#### SafeProtocolManager.sol

```
yarn hardhat verify --network goerli <contract_address> <initial_owner> <registry_address>
```
| Command | Description |
|----------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| ``` yarn hardhat generate:deployments ``` | Generate deployments markdown in [./docs/deployments.md](./docs/deployments.md) from [./deployments.ts](./deployments.ts) |
| ``` yarn hardhat verify --network goerli <contract_address> <initial_owner> ``` | Verify Registry contract(s)<br/> Applicable for<br/> - SafeProtocolRegistry.sol<br/> - TestSafeProtocolRegistryUnrestricted.sol<br/> |
| ``` yarn hardhat verify --network goerli <contract_address> <initial_owner> <registry_address> ``` | Verify SafeProtocolManager.sol |
11 changes: 11 additions & 0 deletions docs/deployments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Deployed Safe{Core} Protocol Contracts

## Network: goerli

| Contract Name | Address (click to view on Etherscan) |
| -------------- | -------------------------------- |
| SafeProtocolManager | <a href="https://goerli.etherscan.io/address/0x4026BA244d773F17FFA2d3173dAFe3fdF94216b9" target="_blank">0x4026BA244d773F17FFA2d3173dAFe3fdF94216b9</a> |
| SafeProtocolRegistry | <a href="https://goerli.etherscan.io/address/0xc9361a1c6A8DeB0e4bB069820BB3f0Eaf94ae829" target="_blank">0xc9361a1c6A8DeB0e4bB069820BB3f0Eaf94ae829</a> |
| TestSafeProtocolRegistryUnrestricted | <a href="https://goerli.etherscan.io/address/0x9EFbBcAD12034BC310581B9837D545A951761F5A" target="_blank">0x9EFbBcAD12034BC310581B9837D545A951761F5A</a> |
| TestSafeProtocolManager | <a href="https://goerli.etherscan.io/address/0xAbd9769A78Ee63632A4fb603D85F63b8D3596DF9" target="_blank">0xAbd9769A78Ee63632A4fb603D85F63b8D3596DF9</a> |

100 changes: 100 additions & 0 deletions docs/execution_flows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# High-level overview of Execution Flows

The below sections provide a high-level overview of the execution different flows for the Safe{Core} Protocol.

## Enable Integration flow

```mermaid
---
title: Safe{Core} Protocol High-level execution flow for enabling Integration
---
flowchart TD;
subgraph Users
User(User)
end
subgraph SafeAccounts
User(User) -->|Call manager to enable Sample Plugin| SafeAccount
end
subgraph SafeProtocolManager
SafeAccount -->|Enable Sample Plugin Tx| Enable_Integration(Enable Integration on a Safe)
Enable_Plugin --> Validator{Is Sample Integration trusted?<br>Call SafeProtocolRegistry}
Validator -- Yes --> C(Sample Integration enabled on Safe)
Validator -- No ----> E(Revert transaction)
end
```



## Transaction execution through Plugin

```mermaid
---
title: Safe{Core} Protocol High-level Plugin execution flow
---
flowchart TD;
TxExecuteFromPlugin(Call to Plugin to execute tx ) --> ExamplePlugin1
Safe --> Execute_Transaction_From_Plugin(Execute transaction)
Validate_ExecuteFromPluginFlow -- Yes --> Safe(Safe Account)
subgraph Plugins
ExamplePlugin1(Sample Plugin)
end
subgraph SafeProtocolManager
ExamplePlugin1 -->|Execute tx for a Safe through Plugin| Execute_Transaction(Execute transaction from a Plugin) --> Validate_ExecuteFromPluginFlow{Is Plugin Enabled?<br>Call SafeProtocolRegistry<br>and validate if Plugin trusted}
Validate_ExecuteFromPluginFlow -- No ----> E(Revert transaction)
end
```

## Safe transaction execution with Hooks

```mermaid
---
title: Safe{Core} Protocol High-level execution flow through Safe
---
flowchart TD;
subgraph Users
User(User)
end
subgraph SafeAccounts
User(User) -->|Execute Safe Tx| SafeAccount
End
end
subgraph SafeAccount [Safe with SafeProtocolManager enabled as Hook]
PreCheck_Hook
PreCheck_Hook("Pre-check Hook") -->|On passing pre-checks| ExecuteTx(Execute Safe Transaction)
ExecuteTx -->|On successful execution| PostCheckHook(Post-check hook)
PostCheckHook -->|On passing post checks| End
end
```

## Signature Verifier

```mermaid
---
title: Safe{Core} Protocol High-level execution flow for signature verification
---
flowchart TD;
Sign_Transaction(Signature forward to a smart contract for validation as input)
subgraph Users
User(User)
end
subgraph SignatureVerifier [Signature verifier enabled for the given Safe]
isValidSignature(isValidSignature)
isValidSignature --> |No| E(Revert transaction)
end
Sign_Transaction --> RequestToValidate
RequestToValidate(Call to validate a Signature for given Safe) --> SafeProtocolManager
SafeProtocolManager --> isValidSignature{isValidSignature}
isValidSignature --> |Yes| ExecuteTx(Continue transaction execution)
User("`Users(s)`") --> |Generate a Safe signature| Sign_Transaction
```
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "hardhat-deploy";
import { DeterministicDeploymentInfo } from "hardhat-deploy/dist/types";
import { getSingletonFactoryInfo } from "@safe-global/safe-singleton-factory";
import { ethers } from "ethers";
import "./src/tasks/generate_deployments_markdown";
import "./src/tasks/show_codesize";

// Load environment variables.
Expand Down
44 changes: 44 additions & 0 deletions src/tasks/generate_deployments_markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// hardhat.config.js
import "hardhat-deploy";
import fs from "fs";
import { task } from "hardhat/config";
import deployments from "../../deployments";
import {NETWORK_ID_URL_MAPPING} from "../utils/etherscan_urls";

task("generate:deployments", "Generate markdown file with deployed contract addresses")
.setAction(async () => {
const markdownFile = "./docs/deployments.md";

const networks = Object.keys(deployments);

if (networks.length === 0) {
console.error("No deployments found in the deployments file.");
return;
}


let markdownContent = "# Deployed Safe{Core} Protocol Contracts\n\n";

networks.forEach((network) => {
if (deployments[network]) {
const contracts = deployments[network][0];

markdownContent += `## Network: ${contracts.name}\n\n`;
markdownContent += "| Contract Name | Address (click to view on Etherscan) |\n";
markdownContent += "| -------------- | -------------------------------- |\n";

Object.keys(contracts.contracts).forEach((contractName) => {
const contractAddress = contracts.contracts[contractName].address;
const etherscanUrl = `${NETWORK_ID_URL_MAPPING[network]}/address/${contractAddress}`;
markdownContent += `| ${contractName} | <a href="${etherscanUrl}" target="_blank">${contractAddress}</a> |\n`;

});

markdownContent += "\n";
}
});

fs.writeFileSync(markdownFile, markdownContent);

console.log(`Markdown file with deployed contract addresses generated: ${markdownFile}`);
});
4 changes: 4 additions & 0 deletions src/utils/etherscan_urls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const ETHERSCAN_GOERLI_BASE_URL = "https://goerli.etherscan.io";
export const NETWORK_ID_URL_MAPPING = {
5: ETHERSCAN_GOERLI_BASE_URL
}

0 comments on commit 0dc36e0

Please sign in to comment.