diff --git a/.gas-snapshot b/.gas-snapshot index de69d7c..66c89ec 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,86 +1,81 @@ BasesTest:testCommonRawStorage() (gas: 7916) -UpgradeableModuleTest:testAvatarCanUpgradeModule() (gas: 32594) -UpgradeableModuleTest:testCommonRawStorage() (gas: 7951) -UpgradeableModuleTest:testNonAvatarCannotUpgrade() (gas: 17744) -UpgradeableModuleTest:testRawStorage() (gas: 8035) +EIP1967UpgradeableTest:testAvatarCanUpgradeModule() (gas: 37091) +EIP1967UpgradeableTest:testCommonRawStorage() (gas: 7951) +EIP1967UpgradeableTest:testNonAvatarCannotUpgrade() (gas: 17719) +EIP1967UpgradeableTest:testRawStorage() (gas: 8043) ZodiacModuleTest:testAvatarCanAddGuard() (gas: 187) -ZodiacModuleTest:testAvatarCanChangeTarget() (gas: 459962) -ZodiacModuleTest:testCanExecuteCall() (gas: 114368) -ZodiacModuleTest:testCannotReinitialize() (gas: 17880) +ZodiacModuleTest:testAvatarCanChangeTarget() (gas: 457598) +ZodiacModuleTest:testCanExecuteCall() (gas: 114404) +ZodiacModuleTest:testCannotReinitialize() (gas: 17898) ZodiacModuleTest:testCommonRawStorage() (gas: 7940) -ZodiacModuleTest:testInitialState() (gas: 22084) +ZodiacModuleTest:testInitialState() (gas: 22128) ZodiacModuleTest:testNonAvatarCannotAddGuard() (gas: 208) -ZodiacModuleTest:testNonAvatarCannotChangeTarget() (gas: 17764) -ZodiacModuleTest:testRawStorage() (gas: 67714) -BudgetTest:testAllowanceChain() (gas: 542793) -BudgetTest:testAllowanceIsKeptTrackOf() (gas: 224722) -BudgetTest:testAllowanceSpenderWithRoleFlags() (gas: 201894) -BudgetTest:testBadTimeshiftsRevert() (gas: 19759) -BudgetTest:testCannotReinit() (gas: 15267) -BudgetTest:testCantExecuteIfNotAuthorized() (gas: 123196) -BudgetTest:testCantExecuteInexistentAllowance() (gas: 16111) -BudgetTest:testCreateAllowance() (gas: 125888) -BudgetTest:testCreateSuballowance() (gas: 303563) -BudgetTest:testCreateSuballowanceWithInheritedRecurrency() (gas: 272595) -BudgetTest:testInitialState() (gas: 18089) -BudgetTest:testMultipleAllowances() (gas: 355661) -BudgetTest:testNotOwnerCannotCreateAllowance() (gas: 24385) -BudgetWithProxyTest:testAllowanceChain() (gas: 551846) -BudgetWithProxyTest:testAllowanceIsKeptTrackOf() (gas: 232542) -BudgetWithProxyTest:testAllowanceSpenderWithRoleFlags() (gas: 207263) -BudgetWithProxyTest:testBadTimeshiftsRevert() (gas: 24555) -BudgetWithProxyTest:testCannotReinit() (gas: 20056) -BudgetWithProxyTest:testCantExecuteIfNotAuthorized() (gas: 128283) -BudgetWithProxyTest:testCantExecuteInexistentAllowance() (gas: 20901) -BudgetWithProxyTest:testCreateAllowance() (gas: 130997) -BudgetWithProxyTest:testCreateSuballowance() (gas: 309563) -BudgetWithProxyTest:testCreateSuballowanceWithInheritedRecurrency() (gas: 278595) -BudgetWithProxyTest:testInitialState() (gas: 23390) -BudgetWithProxyTest:testMultipleAllowances() (gas: 364379) -BudgetWithProxyTest:testNotOwnerCannotCreateAllowance() (gas: 29181) +ZodiacModuleTest:testNonAvatarCannotChangeTarget() (gas: 17739) +ZodiacModuleTest:testRawStorage() (gas: 67713) +BudgetTest:testAllowanceChain() (gas: 567409) +BudgetTest:testAllowanceIsKeptTrackOfOnMulti() (gas: 248829) +BudgetTest:testAllowanceIsKeptTrackOfOnSingle() (gas: 244802) +BudgetTest:testAllowanceSpenderWithRoleFlags() (gas: 213584) +BudgetTest:testBadTimeshiftsRevert() (gas: 29139) +BudgetTest:testCannotReinit() (gas: 20184) +BudgetTest:testCantExecuteIfNotAuthorized() (gas: 134431) +BudgetTest:testCantExecuteInexistentAllowance() (gas: 18902) +BudgetTest:testCantExecuteMultiIfNotAuthorized() (gas: 136362) +BudgetTest:testCreateAllowance():(uint256) (gas: 134161) +BudgetTest:testCreateSuballowance():(uint256,uint256) (gas: 320221) +BudgetTest:testCreateSuballowanceWithInheritedRecurrency() (gas: 289735) +BudgetTest:testDisablingAllowanceBreaksChain() (gas: 577557) +BudgetTest:testInitialState() (gas: 23348) +BudgetTest:testInvalidSpenderReverts() (gas: 37311) +BudgetTest:testMultipleAllowances() (gas: 379002) +BudgetTest:testNonAdminCannotUpdateAllowanceParams() (gas: 340916) +BudgetTest:testNotOwnerCannotCreateTopLevelAllowance() (gas: 21545) +BudgetTest:testOnlyParentAdminCanDisableAllowance() (gas: 574509) +BudgetTest:testRevertOnBadInputToMultiPayment() (gas: 135782) +BudgetTest:testUpdateAllowanceParams() (gas: 150927) TimeShiftLibEncodingTest:testDecodingGas() (gas: 498) TimeShiftLibEncodingTest:testEncodingGas() (gas: 634) TimeShiftLibEncodingTest:testRoundtrips() (gas: 3364) -TimeShiftLibShiftTest:testDaily() (gas: 96021) -TimeShiftLibShiftTest:testGasWorstCase() (gas: 11917) -TimeShiftLibShiftTest:testMonthly() (gas: 56445) -TimeShiftLibShiftTest:testOffsets() (gas: 39132) -TimeShiftLibShiftTest:testQuarterly() (gas: 114360) -TimeShiftLibShiftTest:testSemiyearly() (gas: 113082) -TimeShiftLibShiftTest:testWeekly() (gas: 58691) -TimeShiftLibShiftTest:testYearly() (gas: 37889) -RolesAuthTest:testExplicitAddrIsAuthorized() (gas: 9267) -RolesAuthTest:testRoleFlagsEdgeCases() (gas: 48687) -FirmFactoryIntegrationTest:testExecutingPaymentsFromBudget() (gas: 896394) -FirmFactoryIntegrationTest:testFactoryGas() (gas: 567056) -FirmFactoryIntegrationTest:testInitialState() (gas: 572290) -FirmFactoryIntegrationTest:testModuleUpgrades() (gas: 1362669) +TimeShiftLibShiftTest:testDaily() (gas: 90945) +TimeShiftLibShiftTest:testGasWorstCase() (gas: 11413) +TimeShiftLibShiftTest:testMonthly() (gas: 53376) +TimeShiftLibShiftTest:testOffsets() (gas: 37146) +TimeShiftLibShiftTest:testQuarterly() (gas: 108287) +TimeShiftLibShiftTest:testSemiyearly() (gas: 106929) +TimeShiftLibShiftTest:testWeekly() (gas: 55702) +TimeShiftLibShiftTest:testYearly() (gas: 35843) +RolesAuthTest:testExplicitAddrIsAuthorized() (gas: 9273) +RolesAuthTest:testRoleFlags(uint8) (runs: 256, μ: 43795, ~: 43795) +RolesAuthTest:testRoleFlagsEdgeCases() (gas: 48677) +FirmFactoryIntegrationTest:testExecutingPaymentsFromBudget() (gas: 1182442) +FirmFactoryIntegrationTest:testFactoryGas() (gas: 622323) +FirmFactoryIntegrationTest:testInitialState() (gas: 632679) +FirmFactoryIntegrationTest:testModuleUpgrades() (gas: 1700210) UpgradeableModuleProxyFactoryTest:testReturnData() (gas: 10183) -UpgradeableModuleProxyFactoryTest:testRevert() (gas: 13377) -UpgradeableModuleProxyFactoryTest:testUpgrade() (gas: 127591) -RolesTest:testAdminCanChangeAdminForAdminRole() (gas: 20901) -RolesTest:testAdminCanCreateRoles() (gas: 46229) -RolesTest:testAdminCanGrantAndRevokeRoles() (gas: 59035) -RolesTest:testCanChangeRoleAdmin() (gas: 110381) -RolesTest:testCanOnlyHave256Roles() (gas: 6793262) -RolesTest:testCanSetMultipleRoles() (gas: 137374) -RolesTest:testCannotChangeRoleAdminWithoutRolesManagerRole() (gas: 73600) -RolesTest:testCannotCreateRolesWithoutRolesManagerRole() (gas: 11606) -RolesTest:testCannotReinit() (gas: 11013) -RolesTest:testInitialRoot() (gas: 26518) -RolesTest:testNonAdminCannotGrantRole() (gas: 78218) -RolesTest:testNonAdminCantChangeAdminForAdminRole() (gas: 53101) -RolesTest:testSomeoneWithPermissionCanCreateRolesUntilRevoked() (gas: 60480) -RolesWithProxyTest:testAdminCanChangeAdminForAdminRole() (gas: 25950) -RolesWithProxyTest:testAdminCanCreateRoles() (gas: 51572) -RolesWithProxyTest:testAdminCanGrantAndRevokeRoles() (gas: 65221) -RolesWithProxyTest:testCanChangeRoleAdmin() (gas: 116845) -RolesWithProxyTest:testCanOnlyHave256Roles() (gas: 6870703) -RolesWithProxyTest:testCanSetMultipleRoles() (gas: 144706) -RolesWithProxyTest:testCannotChangeRoleAdminWithoutRolesManagerRole() (gas: 78948) -RolesWithProxyTest:testCannotCreateRolesWithoutRolesManagerRole() (gas: 16393) -RolesWithProxyTest:testCannotReinit() (gas: 15797) -RolesWithProxyTest:testInitialRoot() (gas: 33250) -RolesWithProxyTest:testNonAdminCannotGrantRole() (gas: 83572) -RolesWithProxyTest:testNonAdminCantChangeAdminForAdminRole() (gas: 58713) -RolesWithProxyTest:testSomeoneWithPermissionCanCreateRolesUntilRevoked() (gas: 66116) +UpgradeableModuleProxyFactoryTest:testRevert() (gas: 13344) +UpgradeableModuleProxyFactoryTest:testUpgrade() (gas: 127999) +FirmRelayerTest:testBasicRelay() (gas: 84616) +FirmRelayerTest:testGeneratesTypeHashCorrectly() (gas: 1149800) +FirmRelayerTest:testRelayNonceIncreases() (gas: 111701) +FirmRelayerTest:testRelayWithAssertion() (gas: 88482) +FirmRelayerTest:testRevertOnAssertionFailure() (gas: 85380) +FirmRelayerTest:testRevertOnAssertionOutOfBounds() (gas: 85272) +FirmRelayerTest:testRevertOnBadAssertionIndex() (gas: 84950) +FirmRelayerTest:testRevertOnForgedSignature() (gas: 33134) +FirmRelayerTest:testRevertOnInvalidSignature() (gas: 31568) +FirmRelayerTest:testRevertOnRepeatedNonce() (gas: 105657) +FirmRelayerTest:testRevertOnTargetBadSender() (gas: 64735) +FirmRelayerTest:testSelfRelay() (gas: 47564) +RolesTest:testAdminCanChangeAdminForAdminRole() (gas: 28422) +RolesTest:testAdminCanCreateRoles() (gas: 54336) +RolesTest:testAdminCanGrantAndRevokeRoles() (gas: 69707) +RolesTest:testCanChangeRoleAdmin() (gas: 126012) +RolesTest:testCanOnlyHave256Roles() (gas: 7046464) +RolesTest:testCanSetMultipleRoles() (gas: 151875) +RolesTest:testCannotChangeRoleAdminWithoutRolesManagerRole() (gas: 84698) +RolesTest:testCannotCreateRolesWithoutRolesManagerRole() (gas: 18649) +RolesTest:testCannotReinit() (gas: 15870) +RolesTest:testInitialRoot() (gas: 33662) +RolesTest:testNonAdminCannotGrantRole() (gas: 89377) +RolesTest:testNonAdminCantChangeAdminForAdminRole() (gas: 64280) +RolesTest:testSomeoneWithPermissionCanCreateRolesUntilRevoked() (gas: 72695) diff --git a/deployments/testinprod-factory.json b/deployments/testinprod-factory.json index 43f350d..42d8ae0 100644 --- a/deployments/testinprod-factory.json +++ b/deployments/testinprod-factory.json @@ -1,10 +1,18 @@ { "1": { - "address": "0x7784b0c1c3b7523a9b2243ffbff452d234cb0e11", - "blockNumber": 15483275 + "v0.1.0": { + "address": "0x7784b0c1c3b7523a9b2243ffbff452d234cb0e11", + "blockNumber": 15483275 + } }, "5": { - "address": "0x69a952b2d9404f7b162d0db3df0d1f6e462d448a", - "blockNumber": 7508428 + "v0.1.0": { + "address": "0x69a952b2d9404f7b162d0db3df0d1f6e462d448a", + "blockNumber": 7508428 + }, + "v0.2.0": { + "address": "0xa1b159a50613c8f0c6b01d02b8a2258a94eed480", + "blockNumber": 7638312 + } } } \ No newline at end of file diff --git a/scripts/TestinprodDeploy.sol b/scripts/TestinprodDeploy.sol index 1090526..a4bb315 100644 --- a/scripts/TestinprodDeploy.sol +++ b/scripts/TestinprodDeploy.sol @@ -38,8 +38,8 @@ contract TestinprodDeploy is Test { new UpgradeableModuleProxyFactory(), new FirmRelayer(), safeImpl, - address(new Roles(IAvatar(address(10)), address(0))), - address(new Budget(IAvatar(address(10)), IRoles(address(10)), address(0))) + new Roles(), + new Budget() ); vm.stopBroadcast(); diff --git a/scripts/TestinprodSeedState.sol b/scripts/TestinprodSeedState.sol new file mode 100644 index 0000000..6a5354a --- /dev/null +++ b/scripts/TestinprodSeedState.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.16; + +import 'forge-std/Test.sol'; + +import "gnosis-safe/GnosisSafe.sol"; +import {Roles, IRoles, IAvatar, ONLY_ROOT_ROLE} from "../src/roles/Roles.sol"; +import {Budget, TimeShiftLib, NO_PARENT_ID, NATIVE_ASSET} from "../src/budget/Budget.sol"; +import {TimeShift} from "../src/budget/TimeShiftLib.sol"; +import {BackdoorModule} from "../src/factory/local-utils/BackdoorModule.sol"; +import {roleFlag} from "../src/common/test/mocks/RolesAuthMock.sol"; + +contract TestinProdSeedState is Test { + // send some native asset to safe before running it + function run(GnosisSafe safe) public { + // only works for backdoored firms which have 3 modules: [budget, rolesBackdoor, budgetBackdoor] + (address[] memory modules,) = safe.getModulesPaginated(address(0x1), 3); + + Budget budget = Budget(modules[0]); + Roles roles = Roles(address(budget.roles())); + Roles rolesBackdoor = Roles(modules[1]); + Budget budgetBackdoor = Budget(modules[2]); + + // sanity check + assertEq(budget.moduleId(), "org.firm.budget"); + assertEq(roles.moduleId(), "org.firm.roles"); + assertEq(budgetBackdoor.moduleId(), "org.firm.backdoor"); + assertEq(rolesBackdoor.moduleId(), "org.firm.backdoor"); + assertEq(BackdoorModule(address(budgetBackdoor)).module(), address(budget)); + assertEq(BackdoorModule(address(rolesBackdoor)).module(), address(roles)); + + vm.startBroadcast(); + + uint8 roleId = rolesBackdoor.createRole(ONLY_ROOT_ROLE, "Exec role"); + address[] memory safeOwners = safe.getOwners(); + for (uint256 i = 0; i < safeOwners.length; i++) { + rolesBackdoor.setRole(safeOwners[i], roleId, true); + } + uint256 allowanceId = budgetBackdoor.createAllowance( + NO_PARENT_ID, + roleFlag(roleId), + NATIVE_ASSET, 1 ether, + TimeShift(TimeShiftLib.TimeUnit.Monthly, 0).encode(), + "General budget" + ); + budgetBackdoor.executePayment( + allowanceId, + 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6, // goerli weth + 0.01 ether, + "Wrap some eth" + ); + + vm.stopBroadcast(); + } +} \ No newline at end of file diff --git a/src/factory/FirmFactory.sol b/src/factory/FirmFactory.sol index e40a8bb..f1d8949 100644 --- a/src/factory/FirmFactory.sol +++ b/src/factory/FirmFactory.sol @@ -45,24 +45,19 @@ contract FirmFactory { budgetImpl = _budgetImpl; } - function createFirm(address creator, bool withBackdoors) public returns (GnosisSafe safe) { + function createFirm(address creator, bool withBackdoors, uint256 nonce) public returns (GnosisSafe safe) { address[] memory owners = new address[](1); owners[0] = creator; - return createFirm(owners, 1, withBackdoors); + return createFirm(owners, 1, withBackdoors, nonce); } - function createFirm(address[] memory owners, uint256 requiredSignatures, bool withBackdoors) public returns (GnosisSafe safe) { + function createFirm(address[] memory owners, uint256 requiredSignatures, bool withBackdoors, uint256 nonce) public returns (GnosisSafe safe) { bytes memory installModulesData = abi.encodeCall(this.installModules, (withBackdoors)); bytes memory safeInitData = abi.encodeCall( GnosisSafe.setup, (owners, requiredSignatures, address(this), installModulesData, address(0), address(0), 0, payable(0)) ); - // We set a random nonce to allow for several firms to be created using - // the same initial config. It is possible that at some point we will - // want to allow for counterfactual instantiation which will require - // meaningful nonces - uint256 nonce = block.difficulty; // randao number in POS safe = GnosisSafe(payable(safeFactory.createProxyWithNonce(safeImpl, safeInitData, nonce))); // NOTE: We shouldn't be spending on-chain gas for something that can be fetched off-chain diff --git a/src/factory/TestinprodFactory.sol b/src/factory/TestinprodFactory.sol index 1534608..eef7614 100644 --- a/src/factory/TestinprodFactory.sol +++ b/src/factory/TestinprodFactory.sol @@ -13,14 +13,14 @@ contract TestinprodFactory is FirmFactory { Budget _budgetImpl ) FirmFactory(_safeFactory, _moduleFactory, _relayer, _safeImpl, _rolesImpl, _budgetImpl) {} - function createFirmCopyingSafe(GnosisSafe baseSafe) external returns (GnosisSafe safe) { + function createFirmCopyingSafe(GnosisSafe baseSafe, uint256 nonce) external returns (GnosisSafe safe) { (address[] memory owners, uint256 requiredSignatures) = inspectSafe(baseSafe); - return createFirm(owners, requiredSignatures, false); + return createFirm(owners, requiredSignatures, false, nonce); } - function createBackdooredFirmCopyingSafe(GnosisSafe baseSafe) public returns (GnosisSafe safe) { + function createBackdooredFirmCopyingSafe(GnosisSafe baseSafe, uint256 nonce) public returns (GnosisSafe safe) { (address[] memory owners, uint256 requiredSignatures) = inspectSafe(baseSafe); - return createFirm(owners, requiredSignatures, true); + return createFirm(owners, requiredSignatures, true, nonce); } function inspectSafe(GnosisSafe safe) public view returns (address[] memory owners, uint256 requiredSignatures) { diff --git a/src/factory/local-utils/BackdoorModule.sol b/src/factory/local-utils/BackdoorModule.sol index 626d858..58d5b6d 100644 --- a/src/factory/local-utils/BackdoorModule.sol +++ b/src/factory/local-utils/BackdoorModule.sol @@ -21,6 +21,10 @@ contract BackdoorModule is ZodiacModule { assembly { revert(add(data, 0x20), mload(data)) } + } else { + assembly { + return(add(data, 0x20), mload(data)) + } } } } diff --git a/src/factory/test/FirmFactoryIntegrationTest.t.sol b/src/factory/test/FirmFactoryIntegrationTest.t.sol index d0551ea..17993e3 100644 --- a/src/factory/test/FirmFactoryIntegrationTest.t.sol +++ b/src/factory/test/FirmFactoryIntegrationTest.t.sol @@ -130,7 +130,7 @@ contract FirmFactoryIntegrationTest is FirmTest { } function createFirm(address owner) internal returns (GnosisSafe safe, Budget budget, Roles roles) { - safe = factory.createFirm(owner, false); + safe = factory.createFirm(owner, false, 1); (address[] memory modules,) = safe.getModulesPaginated(address(0x1), 1); budget = Budget(modules[0]); roles = Roles(address(budget.roles()));