Skip to content

Commit

Permalink
Add and use DssSpell
Browse files Browse the repository at this point in the history
  • Loading branch information
horsefacts committed Jul 26, 2022
1 parent 274227e commit f605b8f
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 29 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
[submodule "lib/ds-test"]
path = lib/ds-test
url = https://github.com/dapphub/ds-test
[submodule "lib/ds-spell"]
path = lib/ds-spell
url = https://github.com/dapphub/ds-spell
[submodule "lib/ds-pause"]
path = lib/ds-pause
url = https://github.com/makerdao/ds-pause
1 change: 0 additions & 1 deletion lib/ds-spell
Submodule ds-spell deleted from 132420
67 changes: 67 additions & 0 deletions src/gov/spell.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

// Copyright (C) 2022 Horsefacts <[email protected]>
// Copyright (C) 2020 Maker Ecosystem Growth Holdings, INC.
//
// 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.5.16;

interface PauseLike {
function plot(address,bytes32,bytes calldata,uint256) external;
function exec(address,bytes32,bytes calldata,uint256) external;
function delay() external view returns (uint256);
}

interface ActionLike {
function description() external view returns (string memory);
}

contract DssSpell {

PauseLike public pause;
address public action;
bytes32 public tag;
uint256 public eta;
bytes public sig;
uint256 public expiration;
bool public done;

constructor(address _pause, address _action) public {
pause = PauseLike(_pause);
sig = abi.encodeWithSignature("execute()");
action = _action;
bytes32 _tag;
assembly { _tag := extcodehash(_action) }
tag = _tag;
expiration = now + 30 days;
}

function description() public view returns (string memory) {
return ActionLike(action).description();
}

function schedule() public {
require(now <= expiration, "This contract has expired");
require(eta == 0, "This spell has already been scheduled");
eta = now + pause.delay();
pause.plot(action, tag, sig, eta);
}

function cast() public {
require(!done, "spell-already-cast");
done = true;
pause.exec(action, tag, sig, eta);
}
}
5 changes: 5 additions & 0 deletions src/sum.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ contract Sum is DSNote {
return either(bit == usr, can[bit][usr] == 1);
}

event Caller(address caller);
function caller() external {
emit Caller(msg.sender);
}

// --- Data ---
struct Inc {
uint net; // Net counter value
Expand Down
74 changes: 49 additions & 25 deletions test/gov/gov.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import {DSTest} from "ds-test/test.sol";

import {Sum} from "../../src/sum.sol";
import {CTR} from "../../src/gov/ctr.sol";
import {DssSpell} from "../../src/gov/spell.sol";
import {DSToken} from "ds-token/token.sol";
import {DSChief, DSChiefFab} from "ds-chief/chief.sol";
import {DSPause, DSPauseProxy} from "ds-pause/pause.sol";
import {DSSpell, DSSpellBook} from "ds-spell/spell.sol";

interface VmLike {
function prank(address) external;
Expand All @@ -34,8 +34,23 @@ interface VmLike {
function expectRevert(bytes4) external;
function expectRevert() external;
function label(address, string calldata) external;
function warp(uint256) external;
}

interface SumLike {
function file(bytes32,uint256) external;
}

contract SetOneToTwo {
string constant public description = "Set One to 2";
address constant public sum = address(0xCe71065D4017F316EC606Fe4422e11eB2c47c246);

function execute() external {
SumLike(sum).file("One", 2);
}
}


contract TestGov is DSTest {

// Can't use forge-std Test here
Expand All @@ -48,8 +63,7 @@ contract TestGov is DSTest {
DSChief internal chief;
DSPause internal pause;
DSPauseProxy internal pauseProxy;
DSSpellBook internal spellBook;
DSSpell internal spell;
DssSpell internal spell;

address me = address(this);

Expand All @@ -73,22 +87,8 @@ contract TestGov is DSTest {
pause = new DSPause(172800, address(0), address(chief));
pauseProxy = pause.proxy();

spellBook = new DSSpellBook();

// Assemble the plot
address usr = address(sum);
bytes32 tag; assembly { tag := extcodehash(usr) }
bytes memory fax = abi.encodeWithSignature("file(bytes32,uint)", "One", 2);
uint256 eta = now + pause.delay();

bytes memory plot = abi.encodeWithSignature(
"plot(address,bytes32,bytes memory,uint)",
usr,
tag,
fax,
eta
);
spell = spellBook.make(address(pause), 0, plot);
SetOneToTwo action = new SetOneToTwo();
spell = new DssSpell(address(pause), address(action));
}

function test_governance_deployment() public {
Expand Down Expand Up @@ -164,12 +164,23 @@ contract TestGov is DSTest {
address[] memory dummy = new address[](1);
dummy[0] = address(0);

address[] memory slate = new address[](1);
slate[0] = address(spell);

// Hat is address(0)
assertEq(chief.hat(), address(0));

// Alice votes for dummy slate
vm.prank(alice);
bytes32 dummyId = chief.vote(dummy);

// Chief meets launch limit
assertGt(chief.approvals(address(0)), 80_000 * 10 ** 18);
assertTrue(!chief.live());

// Launch the chief
chief.launch();

address[] memory slate = new address[](1);
slate[0] = address(spell);

// Alice votes for spell slate
vm.prank(alice);
bytes32 slateId = chief.vote(slate);
Expand All @@ -180,7 +191,7 @@ contract TestGov is DSTest {

// Bob votes for dummy slate
vm.prank(bob);
chief.vote(dummy);
chief.vote(dummyId);

// Lift the hat
chief.lift(address(0));
Expand All @@ -194,8 +205,21 @@ contract TestGov is DSTest {
chief.lift(address(spell));
assertEq(chief.hat(), address(spell));

// Cast the spell
//spell.cast();
// Schedule the spell
spell.schedule();

// Warp to plot eta
vm.warp(spell.eta());

// Execute the spell
spell.cast();

// One is now 2
assertEq(sum.One(), 2);

// Spell cannot execute twice
vm.expectRevert("spell-already-cast");
spell.cast();
}

}

0 comments on commit f605b8f

Please sign in to comment.