Skip to content

Commit

Permalink
refactor: move plugins and permissions to registry
Browse files Browse the repository at this point in the history
feat: add "getPluginByProxy" getter
feat: add "getPermissionByProxy" getter
refactor: delete annex
refactor: delete 'system' scripts
refactor: get rid of proxy storage
refactor: rename getters
refactor: rename "selector" param to "method"
test: update tests in light of new contract API
  • Loading branch information
PaulRBerg committed Jun 19, 2023
1 parent ea80da3 commit 37dc8be
Show file tree
Hide file tree
Showing 60 changed files with 644 additions and 688 deletions.
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
17 changes: 7 additions & 10 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,7 +89,8 @@ 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]) {
bool permission = registry.getPermissionByOwner({ owner: owner, envoy: msg.sender, target: target });
if (owner != msg.sender && !permission) {
revert PRBProxy_ExecutionUnauthorized({ owner: owner, caller: msg.sender, target: target });
}

Expand All @@ -105,7 +102,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

0 comments on commit 37dc8be

Please sign in to comment.