Skip to content

Commit

Permalink
feat: Scaffolding for DeployAuthSystem Script (#11908)
Browse files Browse the repository at this point in the history
* feat: Scaffolding for DeployAuthSystem Script

* feat: Remove redundant documentation

* Update DeployAuthSystem.s.sol
  • Loading branch information
maurelian authored Sep 17, 2024
1 parent 3b4fcc5 commit 4490fa8
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 8 deletions.
43 changes: 43 additions & 0 deletions packages/contracts-bedrock/scripts/DeployAuthSystem.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,46 @@ contract DeployAuthSystemOutput is CommonBase {
return _safe;
}
}

contract DeployAuthSystem is Script {
function run(string memory _infile, string memory _outfile) public {
(DeployAuthSystemInput dasi, DeployAuthSystemOutput daso) = etchIOContracts();

dasi.loadInputFile(_infile);

run(dasi, daso);

daso.writeOutputFile(_outfile);
}

function run(DeployAuthSystemInput _dasi, DeployAuthSystemOutput _daso) public {
deploySafe(_dasi, _daso);
}

function deploySafe(DeployAuthSystemInput _dasi, DeployAuthSystemOutput _daso) public {
address[] memory owners = _dasi.owners();
uint256 threshold = _dasi.threshold();

// TODO: replace with a real deployment. The safe deployment logic is fairly complex, so for the purposes of
// this scaffolding PR we'll just etch the code.
address safe = makeAddr("safe");
vm.etch(safe, type(Safe).runtimeCode);
vm.store(safe, bytes32(uint256(3)), bytes32(uint256(owners.length)));
vm.store(safe, bytes32(uint256(4)), bytes32(uint256(threshold)));

_daso.set(_daso.safe.selector, safe);
}

function etchIOContracts() public returns (DeployAuthSystemInput dasi_, DeployAuthSystemOutput daso_) {
(dasi_, daso_) = getIOContracts();
vm.etch(address(dasi_), type(DeployAuthSystemInput).runtimeCode);
vm.etch(address(daso_), type(DeployAuthSystemOutput).runtimeCode);
vm.allowCheatcodes(address(dasi_));
vm.allowCheatcodes(address(daso_));
}

function getIOContracts() public view returns (DeployAuthSystemInput dasi_, DeployAuthSystemOutput daso_) {
dasi_ = DeployAuthSystemInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployAuthSystemInput"));
daso_ = DeployAuthSystemOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployAuthSystemOutput"));
}
}
102 changes: 94 additions & 8 deletions packages/contracts-bedrock/test/DeployAuthSystem.t.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import { Test } from "forge-std/Test.sol";
import { Test, stdStorage, StdStorage } from "forge-std/Test.sol";
import { stdToml } from "forge-std/StdToml.sol";
import { Solarray } from "scripts/libraries/Solarray.sol";

import { DeployAuthSystemInput, DeployAuthSystemOutput } from "scripts/DeployAuthSystem.s.sol";
import { DeployAuthSystemInput, DeployAuthSystem, DeployAuthSystemOutput } from "scripts/DeployAuthSystem.s.sol";

contract DeployAuthSystemInput_Test is Test {
DeployAuthSystemInput dasi;
Expand Down Expand Up @@ -68,13 +68,10 @@ contract DeployAuthSystemOutput_Test is Test {
function test_set_succeeds() public {
address safeAddr = makeAddr("safe");

// Ensure the address has code, since it's expected to be a contract
vm.etch(safeAddr, hex"01");

// Set the output data
daso.set(daso.safe.selector, safeAddr);

// Compare the test data to the getter method
assertEq(safeAddr, address(daso.safe()), "100");
}

Expand All @@ -95,13 +92,11 @@ contract DeployAuthSystemOutput_Test is Test {
function test_writeOutputFile_succeeds() public {
string memory root = vm.projectRoot();

// Use the expected data from the test fixture.
string memory expOutPath = string.concat(root, "/test/fixtures/test-deploy-auth-system-out.toml");
string memory expOutToml = vm.readFile(expOutPath);

address expSafe = expOutToml.readAddress(".safe");

// Etch code at each address so the code checks pass when settings values.
vm.etch(expSafe, hex"01");

daso.set(daso.safe.selector, expSafe);
Expand All @@ -110,9 +105,100 @@ contract DeployAuthSystemOutput_Test is Test {
daso.writeOutputFile(actOutPath);
string memory actOutToml = vm.readFile(actOutPath);

// Clean up before asserting so that we don't leave any files behind.
vm.removeFile(actOutPath);

assertEq(expOutToml, actOutToml);
}
}

contract DeployAuthSystem_Test is Test {
using stdStorage for StdStorage;

DeployAuthSystem deployAuthSystem;
DeployAuthSystemInput dasi;
DeployAuthSystemOutput daso;

// Define default input variables for testing.
uint256 defaultThreshold = 5;
uint256 defaultOwnersLength = 7;
address[] defaultOwners;

function setUp() public {
deployAuthSystem = new DeployAuthSystem();
(dasi, daso) = deployAuthSystem.etchIOContracts();
for (uint256 i = 0; i < defaultOwnersLength; i++) {
defaultOwners.push(makeAddr(string.concat("owner", vm.toString(i))));
}
}

function hash(bytes32 _seed, uint256 _i) internal pure returns (bytes32) {
return keccak256(abi.encode(_seed, _i));
}

function testFuzz_run_memory_succeeds(bytes32 _seed) public {
address[] memory _owners = Solarray.addresses(
address(uint160(uint256(hash(_seed, 0)))),
address(uint160(uint256(hash(_seed, 1)))),
address(uint160(uint256(hash(_seed, 2)))),
address(uint160(uint256(hash(_seed, 3)))),
address(uint160(uint256(hash(_seed, 4)))),
address(uint160(uint256(hash(_seed, 5)))),
address(uint160(uint256(hash(_seed, 6))))
);

uint256 threshold = bound(uint256(_seed), 1, _owners.length - 1);

dasi.set(dasi.owners.selector, _owners);
dasi.set(dasi.threshold.selector, threshold);

deployAuthSystem.run(dasi, daso);

assertNotEq(address(daso.safe()), address(0), "100");
assertEq(daso.safe().getThreshold(), threshold, "200");
// TODO: the getOwners() method requires iterating over the owners linked list.
// Since we're not yet performing a proper deployment of the Safe, this call will revert.
// assertEq(daso.safe().getOwners().length, _owners.length, "300");

// Architecture assertions.
// TODO: these will become relevant as we add more contracts to the auth system, and need to test their
// relationships.

daso.checkOutput();
}

function test_run_io_succeeds() public {
string memory root = vm.projectRoot();
string memory inpath = string.concat(root, "/test/fixtures/test-deploy-auth-system-in.toml");
string memory outpath = string.concat(root, "/.testdata/test-deploy-auth-system-out.toml");

deployAuthSystem.run(inpath, outpath);

string memory actOutToml = vm.readFile(outpath);
string memory expOutToml = vm.readFile(string.concat(root, "/test/fixtures/test-deploy-auth-system-out.toml"));

vm.removeFile(outpath);
assertEq(expOutToml, actOutToml);
}

function test_run_NullInput_reverts() public {
dasi.set(dasi.owners.selector, defaultOwners);
dasi.set(dasi.threshold.selector, defaultThreshold);

// Zero out the owners length slot
uint256 slot = 9;
vm.store(address(dasi), bytes32(uint256(9)), bytes32(0));
vm.expectRevert("DeployAuthSystemInput: owners not set");
deployAuthSystem.run(dasi, daso);
vm.store(address(dasi), bytes32(uint256(9)), bytes32(defaultOwnersLength));

slot = zeroOutSlotForSelector(dasi.threshold.selector);
vm.expectRevert("DeployAuthSystemInput: threshold not set");
deployAuthSystem.run(dasi, daso);
vm.store(address(dasi), bytes32(slot), bytes32(defaultThreshold));
}

function zeroOutSlotForSelector(bytes4 _selector) internal returns (uint256 slot_) {
slot_ = stdstore.enable_packed_slots().target(address(dasi)).sig(_selector).find();
vm.store(address(dasi), bytes32(slot_), bytes32(0));
}
}

0 comments on commit 4490fa8

Please sign in to comment.