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: cleanup for release #2

Merged
merged 21 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1d2a4d0
refactor: clean up code and tests
amusingaxl Apr 25, 2024
0e9fe12
docs: update `DropSpell` natspec
amusingaxl Apr 25, 2024
f5f85ec
refactor: remove custom test script
amusingaxl Apr 25, 2024
f062efe
refactor: update Github actions to run automatically
amusingaxl Apr 25, 2024
8310f46
forge install: dss-test
amusingaxl Apr 25, 2024
8eeac41
refactor: remove forge-std direct dependency
amusingaxl Apr 25, 2024
e4a0cde
refactor: replace forge-st/Test with dss-test/DssTest
amusingaxl Apr 25, 2024
b8601a6
feat: add deployment script
amusingaxl Apr 25, 2024
cd7db94
refactor: reorganize helper test contracts
amusingaxl May 14, 2024
9eeb52c
refactor: remove redundant internal function
amusingaxl May 14, 2024
547473e
refactor: extract `EmergencyDropSpell` into its own file
amusingaxl May 14, 2024
5d05b7f
test: add aftermath condition to `Protego.drop` test cases
amusingaxl May 14, 2024
a3cd851
refactor: remove methods relying on conforming spells
amusingaxl May 15, 2024
6e01020
chore: update NatSpec and remove unused interfaces
amusingaxl May 15, 2024
c095eb0
refactor: add test coverage for drop spell `done()`
amusingaxl May 15, 2024
5ecaf14
docs: fix README format [skip CI]
amusingaxl May 15, 2024
82a8eb3
docs: update README structure
amusingaxl May 15, 2024
4329683
refactor: reorg and add events to `EmergencyDropSpell`
amusingaxl May 16, 2024
d1d56af
refactor: add explicity error msg for `expectRevert`
amusingaxl May 16, 2024
f369273
refactor: remove unsed method from `test/NonConformingSpell`
amusingaxl May 16, 2024
7f454e0
docs: improve natspec structure (skip ci)
amusingaxl May 16, 2024
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: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FOUNDRY_ROOT_CHAINID='number: the ID of the chain'
FOUNDRY_EXPORTS_OVERWRITE_LATEST='bool: whether to override the latest deployment or not'
8 changes: 7 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
name: test

on: workflow_dispatch
on:
push:
branches:
- master
- main
pull_request:

env:
FOUNDRY_PROFILE: ci
ETH_RPC_URL: ${{ secrets.ETH_RPC_URL }}

jobs:
check:
Expand Down
14 changes: 10 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/
# Ignores broadcast logs
broadcast/

# Ignores script config
script/input/**/*.json
!script/input/**/template-*.json
SidestreamColdMelon marked this conversation as resolved.
Show resolved Hide resolved
script/output/**/*.json

# Docs
docs/

# Dotenv file
.env
7 changes: 3 additions & 4 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
branch = v1.1.1
[submodule "lib/dss-test"]
path = lib/dss-test
url = https://github.com/makerdao/dss-test
3 changes: 0 additions & 3 deletions Makefile

This file was deleted.

71 changes: 41 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,59 @@
# protego
# Protego

Protego is a tool to permissionlessly deploy a spell which can be used to drop a particular plan in MakerDAO's Pause contract, or in extreme cases the protego contract can itself be lifted to the hat, allowing any user to permissionlessly drop any scheduled plan.
Protego is a tool to permissionlessly deploy a spell which can be used to drop a particular plan in the `MCD_PAUSE`
contract, or in extreme cases the `Protego` contract can itself be lifted to the hat, allowing any user to
permissionlessly drop any scheduled plan.

## Usage

### Drop an individual plan

Protego contains a factory to permissionlessly create a spell that is able to drop a single plan in the [pause](https://github.com/dapphub/ds-pause).

* `function deploy(DSSpellLike _spell) external returns (address)`
## Context

Used to deploy a single spell that can be elected to a privileged position. This requires that the `_spell` address parameter conforms to a MakerDAO conformant [spell](https://github.com/makerdao/spells-mainnet)
- A `plan` is a scheduled `delegatecall` that exists in [`MCD_PAUSE`](https://github.com/makerdao/ds-pause) and can be
permissionlessly executed.
- Plans in `MCD_PAUSE` are [identified by a unique 32 byte hash](https://github.com/makerdao/ds-pause/blob/master/src/pause.sol#L99).
- A conforming spell here is one where the values returned by `action()`, `tag()`, `sig()` and `eta()` are equal to the
corresponding `plan`, `usr`, `tag`, `fax` and `eta` values respectively. Bad actors could potentially manipulate the
return values of these functions such that they are not equal, which would result in a non-conforming spell.
- Users interacting with `Protego` should **always** assume the spell they want to drop is non-conforming and fetch the
parameters directly from the logs created by [`pause.plot()`](https://etherscan.deth.net/address/0xbe286431454714f511008713973d3b053a2d38f3#L189-L203)

* `function deploy(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta) external returns (address)`

Used to deploy a single spell that can be elected to a privileged position. This can be used to drop a non-conformant spell by reproducing the associated components of the plan.

### Drop any plan
## Usage

In the case of a governance attack, many spells could be plotted quickly by an attacker. To ameliorate this risk, the `protego` contract itself can be elected to a hat role, which permits any user to permissionlessly drop any plan.
### 1. Create a single drop spell

* `function drop(DSSpellLike _spell) external`
```solidity
deploy(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta)(address)
```

Drop a conformant spell from the pause.
If there is sufficient ecosystem interest to cancel (`drop`) a particular scheduled set of actions (the target `plan`),
Protego contains a factory to permissionlessly create a spell ("Emergency Drop Spell"), which – upon being given
the hat – is able to drop the targeted plan in `MCD_PAUSE`.

* `function drop(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta) public`
### 2. Enable permissionless dropping of any plan

Drop a plan from the pause by reproducing the associated components of the plan.
```solidity
drop(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta)
```

## Additional Functions
In case of a governance attack, numerous spells could be created and planned by an attacker at a rate faster than a
single hat spell can `drop` them. To mitigate this risk, the `Protego` contract itself can be given the hat, which
allows any user to permissionlessly drop any plan.

### ID
It will **immediately** drop a plan in `MCD_PAUSE` using the parameters provided.

* `function id(DSSpellLike _spell) public view returns (bytes32)`
* `function id(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta) public pure returns (bytes32)`
## Additional functions

Return the `bytes32` id of a plan in the pause.
### `id()`

### Planned
```solidity
id(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta)(bytes32)
```

* `function planned(DSSpellLike _spell) public view returns (bool)`
* `function planned(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta) public view returns (bool)`
* `function planned(bytes32 _id) public view returns (bool)`
Returns the `bytes32` id of a given plan using the same method that `hash` does in `MCD_PAUSE`.

Returns `true` if a plan has been plotted.
### `planned()`

```solidity
planned(address _usr, bytes32 _tag, bytes memory _fax, uint256 _eta)(bool)
planned(bytes32 _id)(bool)
```

Returns `true` if a plan has been scheduled for execution.
18 changes: 14 additions & 4 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
src = "src"
out = "out"
script = 'script'
libs = ["lib"]
solc = '0.8.16'
optimizer = true

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
fs_permissions = [
{ access = "read", path = "./out/" },
{ access = "read", path = "./script/input/" },
{ access = "read-write", path = "./script/output/" }
SidestreamColdMelon marked this conversation as resolved.
Show resolved Hide resolved
]

[rpc_endpoints]
mainnet = "${ETH_RPC_URL}"
1 change: 1 addition & 0 deletions lib/dss-test
Submodule dss-test added at 6d4029
1 change: 0 additions & 1 deletion lib/forge-std
Submodule forge-std deleted from 054a25
43 changes: 43 additions & 0 deletions script/ProtegoDeploy.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity ^0.8.16;

import {Script} from "forge-std/Script.sol";
import {MCD, DssInstance} from "dss-test/MCD.sol";
import {ScriptTools} from "dss-test/ScriptTools.sol";
import {ProtegoDeploy, ProtegoDeployParams} from "./dependencies/ProtegoDeploy.sol";
import {ProtegoInstance} from "./dependencies/ProtegoInstance.sol";

contract ProtegoDeployScript is Script {
using ScriptTools for string;

string constant NAME = "protego";

address constant CHAINLOG = 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F;
DssInstance dss = MCD.loadFromChainlog(CHAINLOG);
address pause = dss.chainlog.getAddress("MCD_PAUSE");
ProtegoInstance inst;

function run() external {
vm.startBroadcast();

inst = ProtegoDeploy.deploy(ProtegoDeployParams({pause: pause}));

vm.stopBroadcast();

ScriptTools.exportContract(NAME, "protego", inst.protego);
}
}
30 changes: 30 additions & 0 deletions script/dependencies/ProtegoDeploy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity ^0.8.16;

import {ScriptTools} from "dss-test/ScriptTools.sol";
import {Protego} from "src/Protego.sol";
import {ProtegoInstance} from "./ProtegoInstance.sol";

struct ProtegoDeployParams {
address pause;
}

library ProtegoDeploy {
SidestreamColdMelon marked this conversation as resolved.
Show resolved Hide resolved
function deploy(ProtegoDeployParams memory p) internal returns (ProtegoInstance memory r) {
r.protego = address(new Protego(p.pause));
}
}
21 changes: 21 additions & 0 deletions script/dependencies/ProtegoInstance.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity ^0.8.16;

struct ProtegoInstance {
address protego;
}

1 change: 1 addition & 0 deletions script/input/1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Inputs for Mainnet scripts.
1 change: 1 addition & 0 deletions script/output/1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Outputs for Mainnet scripts.
13 changes: 0 additions & 13 deletions script/test.sh

This file was deleted.

Loading
Loading