Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: storage redesign #120

Merged
merged 1 commit into from
Jun 28, 2023
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
2 changes: 1 addition & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"contract-name-camelcase": "off",
"func-name-mixedcase": "off",
"func-visibility": ["error", { "ignoreConstructors": true }],
"max-line-length": ["error", 120],
"max-line-length": ["error", 123],
"no-complex-fallback": "off",
"no-empty-blocks": "off",
"no-inline-assembly": "off",
Expand Down
12 changes: 2 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,8 @@ There are multiple ways to deploy a proxy:
- Call the `deployFor` function, which accepts the owner as an argument.
- Call the `deployAndExecute` function, which deploys the proxy and executes a delegate call to a target contract in a single transaction.

Once the proxy is deployed, you can start interacting with target contracts. PRBProxy ships with an "enshrined" target contract called
`PRBProxyAnnex`, which provides several auxiliary functions, including:

- `installPlugin`
- `setPermission`
- `uninstallPlugin`

You call the functions above by ABI-encoding their calldata and calling `execute` on the proxy. The logic in `PRBProxyAnnex` is kept separate from the
proxy itself to reduce deployment costs.
Once the proxy is deployed, you can start interacting with target contracts by ABI-encoding the target's functions and pass the data to the `execute`
function on the proxy.

### Addresses

Expand All @@ -107,7 +100,6 @@ The registry and the enshrined target are deployed at the same address on the fo
| Contract | Chain | [Chain ID](https://chainlist.org/) | Address |
| -------- | ----------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Registry | Ethereum Goerli Testnet | 5 | [0xa87bc4C1Bc54E1C1B28d2dD942A094A6B665B8C9](https://goerli.etherscan.io/address/0xa87bc4C1Bc54E1C1B28d2dD942A094A6B665B8C9#code) |
| Annex | Ethereum Goerli Testnet | 5 | [0x0254C4467cBbdbe8d5E01e68de0DF7b20dD2A167](https://goerli.etherscan.io/address/0x0254C4467cBbdbe8d5E01e68de0DF7b20dD2A167#code) |

### Targets

Expand Down
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
cbor_metadata = false
evm_version = "paris"
fs_permissions = [{ access = "read", path = "./out-optimized" }]
gas_reports = ["PRBProxy", "PRBProxyAnnex", "PRBProxyRegistry"]
gas_reports = ["PRBProxy", "PRBProxyRegistry"]
ignored_error_codes = [
5159, # ignore selfdestruct warning
]
Expand Down
12 changes: 0 additions & 12 deletions script/DeployAnnex.s.sol

This file was deleted.

16 changes: 0 additions & 16 deletions script/DeployDeterministicAnnex.s.sol

This file was deleted.

23 changes: 0 additions & 23 deletions script/DeployDeterministicSystem.s.sol

This file was deleted.

1 change: 0 additions & 1 deletion script/DeployProxyViaRegistry.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity >=0.8.19 <0.9.0;

import { IPRBProxy } from "../src/interfaces/IPRBProxy.sol";
import { PRBProxyAnnex } from "../src/PRBProxyAnnex.sol";
import { IPRBProxyRegistry } from "../src/interfaces/IPRBProxyRegistry.sol";

import { BaseScript } from "./Base.s.sol";
Expand Down
14 changes: 0 additions & 14 deletions script/DeploySystem.s.sol

This file was deleted.

22 changes: 4 additions & 18 deletions script/SetPermission.s.sol
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19 <0.9.0;

import { IPRBProxy } from "../src/interfaces/IPRBProxy.sol";
import { IPRBProxyAnnex } from "../src/interfaces/IPRBProxyAnnex.sol";
import { IPRBProxyRegistry } from "../src/interfaces/IPRBProxyRegistry.sol";

import { BaseScript } from "./Base.s.sol";

/// @notice Bootstraps the proxy system by giving permission to an envoy and installing a plugin.
/// @notice Permits an envoy to delegate call to a target contract.
contract SetPermission is BaseScript {
function run(
IPRBProxy proxy,
IPRBProxyAnnex annex,
address target
)
public
broadcaster
returns (bytes memory response)
{
// ABI encode the call to `setPermission`.
function run(IPRBProxyRegistry registry, address target, bool permission) public broadcaster {
address envoy = vm.addr(vm.deriveKey(mnemonic, 1));
bool permission = true;
bytes memory data = abi.encodeCall(annex.setPermission, (envoy, target, permission));

// Execute the call to the annex.
response = proxy.execute(address(annex), data);
registry.setPermission({ envoy: envoy, target: target, permission: permission });
}
}
3 changes: 0 additions & 3 deletions shell/prepare-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,12 @@ FOUNDRY_PROFILE=optimized forge build

# Copy the production artifacts
cp out-optimized/PRBProxy.sol/PRBProxy.json $artifacts
cp out-optimized/PRBProxyAnnex.sol/PRBProxyAnnex.json $artifacts
cp out-optimized/PRBProxyRegistry.sol/PRBProxyRegistry.json $artifacts

interfaces=./artifacts/interfaces
cp out-optimized/IPRBProxy.sol/IPRBProxy.json $interfaces
cp out-optimized/IPRBProxyAnnex.sol/IPRBProxyAnnex.json $interfaces
cp out-optimized/IPRBProxyPlugin.sol/IPRBProxyPlugin.json $interfaces
cp out-optimized/IPRBProxyRegistry.sol/IPRBProxyRegistry.json $interfaces
cp out-optimized/IPRBProxyStorage.sol/IPRBProxyStorage.json $interfaces

# Format the artifacts with Prettier
pnpm prettier --write ./artifacts
2 changes: 0 additions & 2 deletions shell/update-precompiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ set -euo pipefail
FOUNDRY_PROFILE=optimized forge build

# Retrieve the raw bytecodes, removing the "0x" prefix
annex=$(cat out-optimized/PRBProxyAnnex.sol/PRBProxyAnnex.json | jq -r '.bytecode.object' | cut -c 3-)
registry=$(cat out-optimized/PRBProxyRegistry.sol/PRBProxyRegistry.json | jq -r '.bytecode.object' | cut -c 3-)

precompiles_path="test/utils/Precompiles.sol"
Expand All @@ -22,7 +21,6 @@ if [ ! -f $precompiles_path ]; then
fi

# Replace the current bytecodes
sd "(BYTECODE_ANNEX =)[^;]+;" "\$1 hex\"$annex\";" $precompiles_path
sd "(BYTECODE_REGISTRY =)[^;]+;" "\$1 hex\"$registry\";" $precompiles_path

# Reformat the code with Forge
Expand Down
21 changes: 10 additions & 11 deletions src/PRBProxy.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

import { PRBProxyStorage } from "./abstracts/PRBProxyStorage.sol";
import { IPRBProxy } from "./interfaces/IPRBProxy.sol";
import { IPRBProxyPlugin } from "./interfaces/IPRBProxyPlugin.sol";
import { IPRBProxyRegistry } from "./interfaces/IPRBProxyRegistry.sol";
Expand All @@ -19,10 +18,7 @@ import { IPRBProxyRegistry } from "./interfaces/IPRBProxyRegistry.sol";

/// @title PRBProxy
/// @dev See the documentation in {IPRBProxy}.
contract PRBProxy is
PRBProxyStorage, // 1 inherited component
IPRBProxy // 1 inherited component
{
contract PRBProxy is IPRBProxy {
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -56,10 +52,10 @@ contract PRBProxy is
/// @notice Fallback function used to run plugins.
/// @dev WARNING: anyone can call this function and thus run any installed plugin.
fallback(bytes calldata data) external payable returns (bytes memory response) {
// Check if the function signature exists in the installed plugins mapping.
IPRBProxyPlugin plugin = plugins[msg.sig];
// Check if the function signature points to a known installed plugin.
IPRBProxyPlugin plugin = registry.getPluginByOwner({ owner: owner, method: msg.sig });
if (address(plugin) == address(0)) {
revert PRBProxy_PluginNotInstalledForMethod({ caller: msg.sender, selector: msg.sig });
revert PRBProxy_PluginNotInstalledForMethod({ caller: msg.sender, owner: owner, method: msg.sig });
}

// Delegate call to the plugin.
Expand Down Expand Up @@ -93,8 +89,11 @@ contract PRBProxy is
/// @inheritdoc IPRBProxy
function execute(address target, bytes calldata data) external payable override returns (bytes memory response) {
// Check that the caller is either the owner or an envoy with permission.
if (owner != msg.sender && !permissions[msg.sender][target]) {
revert PRBProxy_ExecutionUnauthorized({ owner: owner, caller: msg.sender, target: target });
if (owner != msg.sender) {
bool permission = registry.getPermissionByOwner({ owner: owner, envoy: msg.sender, target: target });
if (!permission) {
revert PRBProxy_ExecutionUnauthorized({ owner: owner, caller: msg.sender, target: target });
}
}

// Delegate call to the target contract, and handle the response.
Expand All @@ -105,7 +104,7 @@ contract PRBProxy is
INTERNAL NON-CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/

/// @notice Executes a DELEGATECALL to the provided `target` with the provided `data`.
/// @notice Executes a DELEGATECALL to the provided target with the provided data.
/// @dev Shared logic between the constructor and the `execute` function.
function _execute(address target, bytes memory data) internal returns (bytes memory response) {
// Check that the target is a contract.
Expand Down
94 changes: 0 additions & 94 deletions src/PRBProxyAnnex.sol

This file was deleted.

Loading