diff --git a/.github/workflows/foundry_ci.yml b/.github/workflows/foundry_ci.yml index 4db0facb..3d036548 100644 --- a/.github/workflows/foundry_ci.yml +++ b/.github/workflows/foundry_ci.yml @@ -47,7 +47,7 @@ jobs: - name: Run Forge tests run: | - forge test -vvv --no-match-test "invariant*" + forge test -vvv --no-match-test "invariant*" --no-match-contract "GrantRolesToSafeTest" id: forge-test - name: Run solhint diff --git a/contracts/lib/ProtocolAdmin.sol b/contracts/lib/ProtocolAdmin.sol index bccc48ae..fac042e0 100644 --- a/contracts/lib/ProtocolAdmin.sol +++ b/contracts/lib/ProtocolAdmin.sol @@ -19,4 +19,8 @@ library ProtocolAdmin { /// @notice Guardian role. Grants ability to configure roles. uint64 public constant GUARDIAN_ROLE = 3; string public constant GUARDIAN_ROLE_LABEL = "GUARDIAN_ROLE"; + /// @notice Cancellable admin role. Unlike admin role ide 0 - this role can + /// execute certain admin actions but those can be cancelled by guardian role. + uint64 public constant CANCELLABLE_ADMIN_ROLE = 4; + string public constant CANCELLABLE_ADMIN_ROLE_LABEL = "CANCELLABLE_ADMIN_ROLE"; } diff --git a/foundry.toml b/foundry.toml index bce90073..ca6a52ac 100644 --- a/foundry.toml +++ b/foundry.toml @@ -11,6 +11,8 @@ solc = '0.8.26' fs_permissions = [ { access = 'read-write', path = './deploy-out' }, { access = 'read', path = './out' }, + { access = 'read-write', path = './script/foundry/admin-actions/output' }, + { access = 'read-write', path = './script/foundry/admin-actions/output-test' }, ] ##### Uncomment if running storage layout verification # ffi = true diff --git a/script/foundry/admin-actions/output/1315/grant-new-admin-role-cancel.json b/script/foundry/admin-actions/output/1315/grant-new-admin-role-cancel.json new file mode 100644 index 00000000..ce68fb52 --- /dev/null +++ b/script/foundry/admin-actions/output/1315/grant-new-admin-role-cancel.json @@ -0,0 +1 @@ +[{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d0000000000000000000000004709798fea84c84ae2475ff0c25344115ee1529f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000fe3838bfb30b34170f00030b52ea4893d8aac6bc0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c408d6122d0000000000000000000000001640a22a8a086747cd377b73954545e2dfcc9cad0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024156658500000000000000000000000000000000000000000000000000000000bd6378f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012408d6122d0000000000000000000000009b7a9c70aff961c799110954fc06f3093aeb94c5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd238ab400000000000000000000000000000000000000000000000000000000b33b745700000000000000000000000000000000000000000000000000000000ee2a5307000000000000000000000000000000000000000000000000000000003cd0518b00000000000000000000000000000000000000000000000000000000c14cb98d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e408d6122d000000000000000000000000ffd98c3877b8789124f02c7e8239a4b0ef11e9360000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032939544e00000000000000000000000000000000000000000000000000000000c23c094b000000000000000000000000000000000000000000000000000000001f7f90040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000069d3a7aa9edb72bc226e745a7ccdd50d947b69ac00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000120ef83720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005f0f4426000000000000000000000000000000000000000000000000000000000154cf6d1000000000000000000000000000000000000000000000000000000002bd386530000000000000000000000000000000000000000000000000000000049fb461500000000000000000000000000000000000000000000000000000000520cbac60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001becfc9170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000dd661f55128a80437a0c0bda6e13f214a3b2eb24000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a6bb383300000000000000000000000000000000000000000000000000000000d756a3a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000077319b4031e6ef1250907aa00018b8b1c67a244b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a72a6fa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000529a750e02d8e2f15649c13d69a465286a780e240000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e69a3e70000000000000000000000000000000000000000000000000000000018b00f830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000022dbaaea5d8fb31a0ad793335e39ced5d631fa5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd345302000000000000000000000000000000000000000000000000000000009ab3efe600000000000000000000000000000000000000000000000000000000639cc67d00000000000000000000000000000000000000000000000000000000b18562540000000000000000000000000000000000000000000000000000000053e881cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000084853551b800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001643414e43454c4c41424c455f41444d494e5f524f4c450000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044529629520000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c60000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006425c471a000000000000000000000000000000000000000000000000000000000000000040000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"}] \ No newline at end of file diff --git a/script/foundry/admin-actions/output/1315/grant-new-admin-role-execute.json b/script/foundry/admin-actions/output/1315/grant-new-admin-role-execute.json new file mode 100644 index 00000000..bea66619 --- /dev/null +++ b/script/foundry/admin-actions/output/1315/grant-new-admin-role-execute.json @@ -0,0 +1 @@ +[{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d0000000000000000000000004709798fea84c84ae2475ff0c25344115ee1529f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000fe3838bfb30b34170f00030b52ea4893d8aac6bc0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c408d6122d0000000000000000000000001640a22a8a086747cd377b73954545e2dfcc9cad0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024156658500000000000000000000000000000000000000000000000000000000bd6378f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012408d6122d0000000000000000000000009b7a9c70aff961c799110954fc06f3093aeb94c5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd238ab400000000000000000000000000000000000000000000000000000000b33b745700000000000000000000000000000000000000000000000000000000ee2a5307000000000000000000000000000000000000000000000000000000003cd0518b00000000000000000000000000000000000000000000000000000000c14cb98d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e408d6122d000000000000000000000000ffd98c3877b8789124f02c7e8239a4b0ef11e9360000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032939544e00000000000000000000000000000000000000000000000000000000c23c094b000000000000000000000000000000000000000000000000000000001f7f90040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000069d3a7aa9edb72bc226e745a7ccdd50d947b69ac00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000120ef83720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005f0f4426000000000000000000000000000000000000000000000000000000000154cf6d1000000000000000000000000000000000000000000000000000000002bd386530000000000000000000000000000000000000000000000000000000049fb461500000000000000000000000000000000000000000000000000000000520cbac60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001becfc9170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000dd661f55128a80437a0c0bda6e13f214a3b2eb24000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a6bb383300000000000000000000000000000000000000000000000000000000d756a3a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000077319b4031e6ef1250907aa00018b8b1c67a244b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a72a6fa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000529a750e02d8e2f15649c13d69a465286a780e240000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e69a3e70000000000000000000000000000000000000000000000000000000018b00f830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000022dbaaea5d8fb31a0ad793335e39ced5d631fa5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd345302000000000000000000000000000000000000000000000000000000009ab3efe600000000000000000000000000000000000000000000000000000000639cc67d00000000000000000000000000000000000000000000000000000000b18562540000000000000000000000000000000000000000000000000000000053e881cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084853551b800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001643414e43454c4c41424c455f41444d494e5f524f4c450000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044529629520000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006425c471a000000000000000000000000000000000000000000000000000000000000000040000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"}] \ No newline at end of file diff --git a/script/foundry/admin-actions/output/1315/grant-new-admin-role-schedule.json b/script/foundry/admin-actions/output/1315/grant-new-admin-role-schedule.json new file mode 100644 index 00000000..c3ea777a --- /dev/null +++ b/script/foundry/admin-actions/output/1315/grant-new-admin-role-schedule.json @@ -0,0 +1 @@ +[{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d0000000000000000000000004709798fea84c84ae2475ff0c25344115ee1529f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000fe3838bfb30b34170f00030b52ea4893d8aac6bc0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c408d6122d0000000000000000000000001640a22a8a086747cd377b73954545e2dfcc9cad0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024156658500000000000000000000000000000000000000000000000000000000bd6378f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012408d6122d0000000000000000000000009b7a9c70aff961c799110954fc06f3093aeb94c5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd238ab400000000000000000000000000000000000000000000000000000000b33b745700000000000000000000000000000000000000000000000000000000ee2a5307000000000000000000000000000000000000000000000000000000003cd0518b00000000000000000000000000000000000000000000000000000000c14cb98d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e408d6122d000000000000000000000000ffd98c3877b8789124f02c7e8239a4b0ef11e9360000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032939544e00000000000000000000000000000000000000000000000000000000c23c094b000000000000000000000000000000000000000000000000000000001f7f90040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000069d3a7aa9edb72bc226e745a7ccdd50d947b69ac00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000120ef83720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005f0f4426000000000000000000000000000000000000000000000000000000000154cf6d1000000000000000000000000000000000000000000000000000000002bd386530000000000000000000000000000000000000000000000000000000049fb461500000000000000000000000000000000000000000000000000000000520cbac60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001becfc9170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000dd661f55128a80437a0c0bda6e13f214a3b2eb24000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a6bb383300000000000000000000000000000000000000000000000000000000d756a3a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000077319b4031e6ef1250907aa00018b8b1c67a244b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a72a6fa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000529a750e02d8e2f15649c13d69a465286a780e240000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e69a3e70000000000000000000000000000000000000000000000000000000018b00f830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000022dbaaea5d8fb31a0ad793335e39ced5d631fa5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd345302000000000000000000000000000000000000000000000000000000009ab3efe600000000000000000000000000000000000000000000000000000000639cc67d00000000000000000000000000000000000000000000000000000000b18562540000000000000000000000000000000000000000000000000000000053e881cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084853551b800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001643414e43454c4c41424c455f41444d494e5f524f4c450000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044529629520000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006425c471a000000000000000000000000000000000000000000000000000000000000000040000000000000000000000004b089bf9340ddb02a011471eaa7d8d81c60cb524000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"}] \ No newline at end of file diff --git a/script/foundry/admin-actions/output/1514/grant-new-admin-role-cancel.json b/script/foundry/admin-actions/output/1514/grant-new-admin-role-cancel.json new file mode 100644 index 00000000..6fa11147 --- /dev/null +++ b/script/foundry/admin-actions/output/1514/grant-new-admin-role-cancel.json @@ -0,0 +1 @@ +[{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d0000000000000000000000004709798fea84c84ae2475ff0c25344115ee1529f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000fe3838bfb30b34170f00030b52ea4893d8aac6bc0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c408d6122d0000000000000000000000001640a22a8a086747cd377b73954545e2dfcc9cad0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024156658500000000000000000000000000000000000000000000000000000000bd6378f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012408d6122d0000000000000000000000009b7a9c70aff961c799110954fc06f3093aeb94c5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd238ab400000000000000000000000000000000000000000000000000000000b33b745700000000000000000000000000000000000000000000000000000000ee2a5307000000000000000000000000000000000000000000000000000000003cd0518b00000000000000000000000000000000000000000000000000000000c14cb98d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e408d6122d000000000000000000000000ffd98c3877b8789124f02c7e8239a4b0ef11e9360000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032939544e00000000000000000000000000000000000000000000000000000000c23c094b000000000000000000000000000000000000000000000000000000001f7f90040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000069d3a7aa9edb72bc226e745a7ccdd50d947b69ac00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000120ef83720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005f0f4426000000000000000000000000000000000000000000000000000000000154cf6d1000000000000000000000000000000000000000000000000000000002bd386530000000000000000000000000000000000000000000000000000000049fb461500000000000000000000000000000000000000000000000000000000520cbac60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001becfc9170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000dd661f55128a80437a0c0bda6e13f214a3b2eb24000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a6bb383300000000000000000000000000000000000000000000000000000000d756a3a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000077319b4031e6ef1250907aa00018b8b1c67a244b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a72a6fa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000529a750e02d8e2f15649c13d69a465286a780e240000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e69a3e70000000000000000000000000000000000000000000000000000000018b00f830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000022dbaaea5d8fb31a0ad793335e39ced5d631fa5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd345302000000000000000000000000000000000000000000000000000000009ab3efe600000000000000000000000000000000000000000000000000000000639cc67d00000000000000000000000000000000000000000000000000000000b18562540000000000000000000000000000000000000000000000000000000053e881cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000084853551b800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001643414e43454c4c41424c455f41444d494e5f524f4c450000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044529629520000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xd6bb62c6000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006425c471a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000000000000000000000000000000000000006978000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-cancel"}] \ No newline at end of file diff --git a/script/foundry/admin-actions/output/1514/grant-new-admin-role-execute.json b/script/foundry/admin-actions/output/1514/grant-new-admin-role-execute.json new file mode 100644 index 00000000..a8499baf --- /dev/null +++ b/script/foundry/admin-actions/output/1514/grant-new-admin-role-execute.json @@ -0,0 +1 @@ +[{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d0000000000000000000000004709798fea84c84ae2475ff0c25344115ee1529f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000fe3838bfb30b34170f00030b52ea4893d8aac6bc0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c408d6122d0000000000000000000000001640a22a8a086747cd377b73954545e2dfcc9cad0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024156658500000000000000000000000000000000000000000000000000000000bd6378f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012408d6122d0000000000000000000000009b7a9c70aff961c799110954fc06f3093aeb94c5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd238ab400000000000000000000000000000000000000000000000000000000b33b745700000000000000000000000000000000000000000000000000000000ee2a5307000000000000000000000000000000000000000000000000000000003cd0518b00000000000000000000000000000000000000000000000000000000c14cb98d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e408d6122d000000000000000000000000ffd98c3877b8789124f02c7e8239a4b0ef11e9360000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032939544e00000000000000000000000000000000000000000000000000000000c23c094b000000000000000000000000000000000000000000000000000000001f7f90040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000069d3a7aa9edb72bc226e745a7ccdd50d947b69ac00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000120ef83720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005f0f4426000000000000000000000000000000000000000000000000000000000154cf6d1000000000000000000000000000000000000000000000000000000002bd386530000000000000000000000000000000000000000000000000000000049fb461500000000000000000000000000000000000000000000000000000000520cbac60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001becfc9170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000dd661f55128a80437a0c0bda6e13f214a3b2eb24000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a6bb383300000000000000000000000000000000000000000000000000000000d756a3a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000077319b4031e6ef1250907aa00018b8b1c67a244b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a72a6fa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000529a750e02d8e2f15649c13d69a465286a780e240000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e69a3e70000000000000000000000000000000000000000000000000000000018b00f830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000022dbaaea5d8fb31a0ad793335e39ced5d631fa5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd345302000000000000000000000000000000000000000000000000000000009ab3efe600000000000000000000000000000000000000000000000000000000639cc67d00000000000000000000000000000000000000000000000000000000b18562540000000000000000000000000000000000000000000000000000000053e881cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084853551b800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001643414e43454c4c41424c455f41444d494e5f524f4c450000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044529629520000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0x1cff79cd000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006425c471a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000000000000000000000000000000000000006978000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-execute"}] \ No newline at end of file diff --git a/script/foundry/admin-actions/output/1514/grant-new-admin-role-schedule.json b/script/foundry/admin-actions/output/1514/grant-new-admin-role-schedule.json new file mode 100644 index 00000000..a401d97f --- /dev/null +++ b/script/foundry/admin-actions/output/1514/grant-new-admin-role-schedule.json @@ -0,0 +1 @@ +[{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d0000000000000000000000004709798fea84c84ae2475ff0c25344115ee1529f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000fe3838bfb30b34170f00030b52ea4893d8aac6bc0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012de906760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c408d6122d0000000000000000000000001640a22a8a086747cd377b73954545e2dfcc9cad0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024156658500000000000000000000000000000000000000000000000000000000bd6378f80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012408d6122d0000000000000000000000009b7a9c70aff961c799110954fc06f3093aeb94c5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd238ab400000000000000000000000000000000000000000000000000000000b33b745700000000000000000000000000000000000000000000000000000000ee2a5307000000000000000000000000000000000000000000000000000000003cd0518b00000000000000000000000000000000000000000000000000000000c14cb98d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e408d6122d000000000000000000000000ffd98c3877b8789124f02c7e8239a4b0ef11e9360000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032939544e00000000000000000000000000000000000000000000000000000000c23c094b000000000000000000000000000000000000000000000000000000001f7f90040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000069d3a7aa9edb72bc226e745a7ccdd50d947b69ac00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000120ef83720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005f0f4426000000000000000000000000000000000000000000000000000000000154cf6d1000000000000000000000000000000000000000000000000000000002bd386530000000000000000000000000000000000000000000000000000000049fb461500000000000000000000000000000000000000000000000000000000520cbac60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d000000000000000000000000d2f60c40febccf6311f8b47c4f2ec6b040400086000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001becfc9170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000dd661f55128a80437a0c0bda6e13f214a3b2eb24000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a6bb383300000000000000000000000000000000000000000000000000000000d756a3a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a408d6122d00000000000000000000000077319b4031e6ef1250907aa00018b8b1c67a244b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a72a6fa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d530000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c408d6122d000000000000000000000000529a750e02d8e2f15649c13d69a465286a780e240000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e69a3e70000000000000000000000000000000000000000000000000000000018b00f830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012408d6122d000000000000000000000000022dbaaea5d8fb31a0ad793335e39ced5d631fa5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005bd345302000000000000000000000000000000000000000000000000000000009ab3efe600000000000000000000000000000000000000000000000000000000639cc67d00000000000000000000000000000000000000000000000000000000b18562540000000000000000000000000000000000000000000000000000000053e881cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084853551b800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001643414e43454c4c41424c455f41444d494e5f524f4c450000000000000000000000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d53000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044529629520000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"},{"from":"0xF07cA4b61022F0399C1511E7E668A57567f2138B","to":"0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53","value":0,"data":"0xf801a698000000000000000000000000fdece7b8a2f55cec33b53fd28936b4b1e3153d5300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006425c471a00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000f07ca4b61022f0399c1511e7e668a57567f2138b000000000000000000000000000000000000000000000000000000000006978000000000000000000000000000000000000000000000000000000000","operation":0,"comment":"grant-new-admin-role-schedule"}] \ No newline at end of file diff --git a/script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol b/script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol new file mode 100644 index 00000000..44a9ed3f --- /dev/null +++ b/script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; + +import { AccessManagerOperations } from "../utils/AccessManagerOperations.s.sol"; +import { Script } from "forge-std/Script.sol"; + +contract GrantRolesToSafe is Script, AccessManagerOperations { + uint64 internal constant ADMIN_ROLE_ID = 0; + uint64 internal constant UPGRADER_ROLE_ID = 1; + uint64 internal constant PAUSE_ROLE_ID = 2; + uint64 internal constant GUARDIAN_ROLE_ID = 3; + + uint32 delay; + + address oldAdmin; + address oldUpgrader; + address oldPauseAdmin1; + address oldPauseAdmin2; + address oldGuardian; + + address governanceSafeMultisig; + address securityCouncilSafeMultisig; + + // Mainnet + // forge script script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol:GrantRolesToSafe --rpc-url https://mainnet.storyrpc.io --legacy --sig "run(address,address,bool,bool)" 0xF07cA4b61022F0399C1511E7E668A57567f2138B 0x25D2605b2C768082A14E79713114389d0eC297D8 false false + + // Aeneid real + // forge script script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol:GrantRolesToSafe --rpc-url https://aeneid.storyrpc.io --legacy --sig "run(address,address,bool,bool)" 0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524 0xC9a862Df1872402c4eAcbb8402F9BE628B52d270 false false + + // Aeneid test + // forge script script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol:GrantRolesToSafe --rpc-url https://aeneid.storyrpc.io --legacy --sig "run(address,address,bool,bool)" 0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524 0xC9a862Df1872402c4eAcbb8402F9BE628B52d270 false true + + function run(address _governanceSafeMultisig, address _securityCouncilSafeMultisig, bool _isUnitTest, bool _isAeneidTest) public { + uint256 chainId = block.chainid; + if (chainId != 1315 && chainId != 1514) revert("Invalid chain id"); + + setAction("grant-roles-to-safe"); + setIsTest(_isUnitTest, _isAeneidTest); + + if (chainId == 1514) { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + delay = 5 days; + oldAdmin = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldUpgrader = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldPauseAdmin1 = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2 = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldGuardian = 0x76430daA671BE12200Cd424Ea6bdd8129A769033; + } + if (chainId == 1315 && !_isAeneidTest) { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Aeneid real + delay = 10 minutes; + oldAdmin = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldUpgrader = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldPauseAdmin1 = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2 = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldGuardian = address(0); + } + if (chainId == 1315 && _isAeneidTest) { + protocolAccessManager = AccessManager(0x7fc3eD9B2CC14C0872ec633c6CC290b8B9B3AA5A); + delay = 10 minutes; + oldAdmin = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldUpgrader = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldPauseAdmin1 = 0x3b3fFAA254d9dCEEA4D59ae1dF28c9F84D4eE901; + oldPauseAdmin2 = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldGuardian = 0x76430daA671BE12200Cd424Ea6bdd8129A769033; + } + + _checkInitialConditions(_isAeneidTest); + + governanceSafeMultisig = _governanceSafeMultisig; + securityCouncilSafeMultisig = _securityCouncilSafeMultisig; + + super.run(); + } + + function _checkInitialConditions(bool _isAeneidTest) internal { + // Admin role + (bool hasRoleOldAdmin, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdmin); + if (!hasRoleOldAdmin) revert ("Old admin role not present"); + + // Upgrader role + (bool hasRoleOldUpgrader, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgrader); + if (!hasRoleOldUpgrader) revert ("Old upgrader role not present"); + + // Pauser role + (bool hasRoleOldPauseAdmin1, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1); + (bool hasRoleOldPauseAdmin2, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2); + if (!hasRoleOldPauseAdmin1) revert ("Old pause admin role 1 not present"); + if (!hasRoleOldPauseAdmin2) revert ("Old pause admin role 2 not present"); + + // Guardian role + (bool hasRoleOldGuardian, ) = protocolAccessManager.hasRole(GUARDIAN_ROLE_ID, oldGuardian); + if (block.chainid != 1315 && !hasRoleOldGuardian) revert ("Old guardian role not present"); + // Aeneid real deployment does not have any address with guardian role so we don't need to check for it + if (block.chainid == 1315 && _isAeneidTest) { + if (!hasRoleOldGuardian) revert ("Old guardian role present"); + } + } + + function _generate() internal virtual override { + address[] memory from = new address[](3); + from[0] = oldAdmin; + from[1] = oldAdmin; + from[2] = oldAdmin; // there is no guardian for grantRole() function so only admin role cancel + + bytes4 selector = protocolAccessManager.grantRole.selector; + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, ADMIN_ROLE_ID, governanceSafeMultisig, delay), + delay + ); + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, UPGRADER_ROLE_ID, governanceSafeMultisig, delay), + delay + ); + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, PAUSE_ROLE_ID, governanceSafeMultisig, 0), + delay + ); + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, GUARDIAN_ROLE_ID, securityCouncilSafeMultisig, delay), + delay + ); + } +} \ No newline at end of file diff --git a/script/foundry/migrate-to-safe/2.RemoveRolesFromNonSafe.s.sol b/script/foundry/migrate-to-safe/2.RemoveRolesFromNonSafe.s.sol new file mode 100644 index 00000000..9ac1be06 --- /dev/null +++ b/script/foundry/migrate-to-safe/2.RemoveRolesFromNonSafe.s.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; + +import { AccessManagerOperations } from "../utils/AccessManagerOperations.s.sol"; +import { Script, console } from "forge-std/Script.sol"; + +contract RemoveRolesFromNonSafe is Script, AccessManagerOperations { + uint64 internal constant ADMIN_ROLE_ID = 0; + uint64 internal constant UPGRADER_ROLE_ID = 1; + uint64 internal constant PAUSE_ROLE_ID = 2; + uint64 internal constant GUARDIAN_ROLE_ID = 3; + + uint32 delay; + + address oldAdmin; + address oldUpgrader; + address oldPauseAdmin1; + address oldPauseAdmin2; + address oldGuardian; + + address governanceSafeMultisig; + address securityCouncilSafeMultisig; + + // Mainnet + // forge script script/foundry/migrate-to-safe/2.RemoveRolesFromNonSafe.s.sol:RemoveRolesFromNonSafe --rpc-url https://mainnet.storyrpc.io --legacy --sig "run(address,address,bool,bool)" $GOVERNANCE_SAFE_ADDRESS_MAINNET $SECURITY_COUNCIL_SAFE_ADDRESS_MAINNET false false + + // Aeneid + // forge script script/foundry/migrate-to-safe/2.RemoveRolesFromNonSafe.s.sol:RemoveRolesFromNonSafe --rpc-url https://aeneid.storyrpc.io --legacy --sig "run(address,address,bool,bool)" $GOVERNANCE_SAFE_ADDRESS_AENEID $SECURITY_COUNCIL_SAFE_ADDRESS_AENEID false false + + function run(address _governanceSafeMultisig, address _securityCouncilSafeMultisig, bool _isUnitTest, bool _isAeneidTest) public { + uint256 chainId = block.chainid; + if (chainId != 1315 && chainId != 1514) revert("Invalid chain id"); + + setAction("remove-roles-from-non-safe"); + setIsTest(_isUnitTest, _isAeneidTest); + + if (chainId == 1514) { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + delay = 5 days; + oldAdmin = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldUpgrader = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldPauseAdmin1 = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2 = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldGuardian = 0x76430daA671BE12200Cd424Ea6bdd8129A769033; + } else if (chainId == 1315) { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + delay = 10 minutes; + oldAdmin = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldUpgrader = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldPauseAdmin1 = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2 = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldGuardian = address(0); + } + + governanceSafeMultisig = _governanceSafeMultisig; + securityCouncilSafeMultisig = _securityCouncilSafeMultisig; + + _checkInitialConditions(); + + super.run(); + } + + function _checkInitialConditions() internal { + // Admin role + (bool hasRoleOldAdmin, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdmin); + (bool hasRoleGovernanceSafeMultisig, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisig); + if (!hasRoleOldAdmin) revert ("Old admin role not present"); + if (!hasRoleGovernanceSafeMultisig) revert ("Governance safe multisig role not present"); + + // Upgrader role + (bool hasRoleOldUpgrader, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgrader); + (bool hasRoleSecurityCouncilSafeMultisig, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, governanceSafeMultisig); + if (!hasRoleOldUpgrader) revert ("Old upgrader role not present"); + if (!hasRoleSecurityCouncilSafeMultisig) revert ("Security council safe multisig role not present"); + + // Pauser role + (bool hasRoleOldPauseAdmin1, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1); + (bool hasRoleOldPauseAdmin2, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2); + (bool hasRoleGovernanceSafeMultisigPause, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisig); + if (!hasRoleOldPauseAdmin1) revert ("Old pause admin role 1 not present"); + if (!hasRoleOldPauseAdmin2) revert ("Old pause admin role 2 not present"); + if (!hasRoleGovernanceSafeMultisigPause) revert ("Governance safe multisig pause role not present"); + + // Guardian role + (bool hasRoleOldGuardian, ) = protocolAccessManager.hasRole(GUARDIAN_ROLE_ID, oldGuardian); + (bool hasRoleSecurityCouncilSafeMultisigGuardian, ) = protocolAccessManager.hasRole(GUARDIAN_ROLE_ID, securityCouncilSafeMultisig); + if (!hasRoleSecurityCouncilSafeMultisigGuardian) revert ("Security council safe multisig guardian role not present"); + // Aeneid does not have any address with guardian role so we don't need to check for it + if (block.chainid != 1315 && !hasRoleOldGuardian) revert ("Old guardian role not present"); + } + + function _generate() internal virtual override { + address[] memory from = new address[](3); + from[0] = governanceSafeMultisig; + from[1] = governanceSafeMultisig; + from[2] = governanceSafeMultisig; + + bytes4 selector = protocolAccessManager.revokeRole.selector; + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, ADMIN_ROLE_ID, oldAdmin), + delay + ); + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, UPGRADER_ROLE_ID, oldUpgrader), + delay + ); + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, PAUSE_ROLE_ID, oldPauseAdmin1), + delay + ); + + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, PAUSE_ROLE_ID, oldPauseAdmin2), + delay + ); + + // Aeneid does not have any address with guardian role so we don't need to check for it + if (block.chainid == 1514) { + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(selector, GUARDIAN_ROLE_ID, oldGuardian), + delay + ); + } + } +} \ No newline at end of file diff --git a/script/foundry/new-admin-role/GrantNewAdminRole.s.sol b/script/foundry/new-admin-role/GrantNewAdminRole.s.sol new file mode 100644 index 00000000..6f9971a4 --- /dev/null +++ b/script/foundry/new-admin-role/GrantNewAdminRole.s.sol @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.26; + +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; + +import { AccessManagerOperations } from "../utils/AccessManagerOperations.s.sol"; +import { ProtocolAdmin } from "../../../contracts/lib/ProtocolAdmin.sol"; +import { GroupNFT } from "../../../contracts/GroupNFT.sol"; +import { LicenseToken } from "../../../contracts/LicenseToken.sol"; +import { IPGraphACL } from "../../../contracts/access/IPGraphACL.sol"; +import { DisputeModule } from "../../../contracts/modules/dispute/DisputeModule.sol"; +import { ArbitrationPolicyUMA } from "../../../contracts/modules/dispute/policies/UMA/ArbitrationPolicyUMA.sol"; +import { GroupingModule } from "../../../contracts/modules/grouping/GroupingModule.sol"; +import { RoyaltyModule } from "../../../contracts/modules/royalty/RoyaltyModule.sol"; +import { VaultController } from "../../../contracts/modules/royalty/policies/VaultController.sol"; +import { ProtocolPauseAdmin } from "../../../contracts/pause/ProtocolPauseAdmin.sol"; +import { IPAssetRegistry } from "../../../contracts/registries/IPAssetRegistry.sol"; +import { LicenseRegistry } from "../../../contracts/registries/LicenseRegistry.sol"; +import { ModuleRegistry } from "../../../contracts/registries/ModuleRegistry.sol"; + +import { Script } from "forge-std/Script.sol"; + +contract GrantNewAdminRole is Script, AccessManagerOperations { + uint32 delay; + address guardianSafeMultisig; + address governanceSafeMultisig; + address groupNftAddr; + address licenseTokenAddr; + address ipGraphACLAddr; + address arbitrationPolicyUmaAddr; + address disputeModuleAddr; + address groupingModuleAddr; + address ipAssetRegistryAddr; + address licenseRegistryAddr; + address moduleRegistryAddr; + address royaltyModuleAddr; + address protocolPauseAdminAddr; + + function run(bool _isUnitTest) public { + uint256 chainId = block.chainid; + if (chainId != 1315 && chainId != 1514) revert("Invalid chain id"); + + setAction("grant-new-admin-role"); + setIsTest(_isUnitTest, false); + + if (chainId == 1514) { + delay = 5 days; + guardianSafeMultisig = 0x25D2605b2C768082A14E79713114389d0eC297D8; + governanceSafeMultisig = 0xF07cA4b61022F0399C1511E7E668A57567f2138B; + + } else if (chainId == 1315) { + delay = 10 minutes; + guardianSafeMultisig = 0xC9a862Df1872402c4eAcbb8402F9BE628B52d270; + governanceSafeMultisig = 0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524; + } + + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + groupNftAddr = 0x4709798FeA84C84ae2475fF0c25344115eE1529f; + licenseTokenAddr = 0xFe3838BFb30B34170F00030B52eA4893d8aAC6bC; + ipGraphACLAddr = 0x1640A22a8A086747cD377b73954545e2Dfcc9Cad; + arbitrationPolicyUmaAddr = 0xfFD98c3877B8789124f02C7E8239A4b0Ef11E936; + disputeModuleAddr = 0x9b7A9c70AFF961C799110954fc06F3093aeb94C5; + groupingModuleAddr = 0x69D3a7aa9edb72Bc226E745A7cCdd50D947b69Ac; + ipAssetRegistryAddr = 0x77319B4031e6eF1250907aa00018B8B1c67a244b; + licenseRegistryAddr = 0x529a750E02d8E2f15649c13D69a465286a780e24; + moduleRegistryAddr = 0x022DBAAeA5D8fB31a0Ad793335e39Ced5D631fa5; + royaltyModuleAddr = 0xD2f60c40fEbccf6311f8B47c4f2Ec6b040400086; + protocolPauseAdminAddr = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + + super.run(); + } + + function _generate() internal virtual override { + address[] memory from = new address[](3); + from[0] = governanceSafeMultisig; + from[1] = governanceSafeMultisig; + from[2] = governanceSafeMultisig; + + // add function selectors to new admin role + bytes4[] memory selectorsGroupNFT = new bytes4[](1); + selectorsGroupNFT[0] = GroupNFT.setLicensingImageUrl.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, groupNftAddr, selectorsGroupNFT, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsLicenseToken = new bytes4[](1); + selectorsLicenseToken[0] = LicenseToken.setLicensingImageUrl.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, licenseTokenAddr, selectorsLicenseToken, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsIPGraphACL = new bytes4[](2); + selectorsIPGraphACL[0] = IPGraphACL.whitelistAddress.selector; + selectorsIPGraphACL[1] = IPGraphACL.revokeWhitelistedAddress.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, ipGraphACLAddr, selectorsIPGraphACL, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsDisputeModule = new bytes4[](5); + selectorsDisputeModule[0] = DisputeModule.whitelistDisputeTag.selector; + selectorsDisputeModule[1] = DisputeModule.whitelistArbitrationPolicy.selector; + selectorsDisputeModule[2] = DisputeModule.setArbitrationRelayer.selector; + selectorsDisputeModule[3] = DisputeModule.setBaseArbitrationPolicy.selector; + selectorsDisputeModule[4] = DisputeModule.setArbitrationPolicyCooldown.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, disputeModuleAddr, selectorsDisputeModule, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsArbitrationPolicyUMA = new bytes4[](3); + selectorsArbitrationPolicyUMA[0] = ArbitrationPolicyUMA.setOOV3.selector; + selectorsArbitrationPolicyUMA[1] = ArbitrationPolicyUMA.setLiveness.selector; + selectorsArbitrationPolicyUMA[2] = ArbitrationPolicyUMA.setMaxBond.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, arbitrationPolicyUmaAddr, selectorsArbitrationPolicyUMA, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsGroupingModule = new bytes4[](1); + selectorsGroupingModule[0] = GroupingModule.whitelistGroupRewardPool.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, groupingModuleAddr, selectorsGroupingModule, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsRoyaltyModule = new bytes4[](5); + selectorsRoyaltyModule[0] = RoyaltyModule.setTreasury.selector; + selectorsRoyaltyModule[1] = RoyaltyModule.setRoyaltyFeePercent.selector; + selectorsRoyaltyModule[2] = RoyaltyModule.setRoyaltyLimits.selector; + selectorsRoyaltyModule[3] = RoyaltyModule.whitelistRoyaltyPolicy.selector; + selectorsRoyaltyModule[4] = RoyaltyModule.whitelistRoyaltyToken.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, royaltyModuleAddr, selectorsRoyaltyModule, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsVaultController = new bytes4[](1); + selectorsVaultController[0] = VaultController.setIpRoyaltyVaultBeacon.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, royaltyModuleAddr, selectorsVaultController, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsProtocolPauseAdmin = new bytes4[](2); + selectorsProtocolPauseAdmin[0] = ProtocolPauseAdmin.addPausable.selector; + selectorsProtocolPauseAdmin[1] = ProtocolPauseAdmin.removePausable.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, protocolPauseAdminAddr, selectorsProtocolPauseAdmin, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsIPAssetRegistry = new bytes4[](1); + selectorsIPAssetRegistry[0] = IPAssetRegistry.setRegistrationFee.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, ipAssetRegistryAddr, selectorsIPAssetRegistry, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsLicenseRegistry = new bytes4[](2); + selectorsLicenseRegistry[0] = LicenseRegistry.setDefaultLicenseTerms.selector; + selectorsLicenseRegistry[1] = LicenseRegistry.registerLicenseTemplate.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, licenseRegistryAddr, selectorsLicenseRegistry, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + bytes4[] memory selectorsModuleRegistry = new bytes4[](5); + selectorsModuleRegistry[0] = ModuleRegistry.registerModuleType.selector; + selectorsModuleRegistry[1] = ModuleRegistry.removeModuleType.selector; + selectorsModuleRegistry[2] = bytes4(keccak256("registerModule(string,address)")); + selectorsModuleRegistry[3] = bytes4(keccak256("registerModule(string,address,string)")); + selectorsModuleRegistry[4] = ModuleRegistry.removeModule.selector; + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setTargetFunctionRole.selector, moduleRegistryAddr, selectorsModuleRegistry, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), + delay + ); + + // create label for role + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.labelRole.selector, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE_LABEL), + delay + ); + + // set guardian role for new admin role + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.setRoleGuardian.selector, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE, ProtocolAdmin.GUARDIAN_ROLE), + delay + ); + + // grant new admin role to governanceSafeMultisig + _generateAction( + from, + address(protocolAccessManager), + 0, + abi.encodeWithSelector(AccessManager.grantRole.selector, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE, governanceSafeMultisig, delay), + delay + ); + } +} \ No newline at end of file diff --git a/script/foundry/utils/AccessManagerOperations.s.sol b/script/foundry/utils/AccessManagerOperations.s.sol new file mode 100644 index 00000000..b4e2c20f --- /dev/null +++ b/script/foundry/utils/AccessManagerOperations.s.sol @@ -0,0 +1,117 @@ +/* solhint-disable no-console */ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; + +import { console2 } from "forge-std/console2.sol"; +import { Script } from "forge-std/Script.sol"; + +// script +import { JSONTxWriter } from "./JSONTxWriter.s.sol"; + +/// @title AccessManagerOperations +/// @notice Script to generate tx json to schedule, execute, and cancel upgrades for the protocol +/// through the AccessManager via multisig. +abstract contract AccessManagerOperations is Script, JSONTxWriter { + AccessManager internal protocolAccessManager; + + function run() public virtual { + console2.log("Generating actions..."); + _generate(); + console2.log("Writing tx json..."); + _writeFiles(); + } + + /// @notice generate the tx json. Should be overridden by the child contract + /// @dev Child contract should call _generateAction for each action to be scheduled, executed, and cancelled + function _generate() internal virtual; + + /// @notice generate the 3 JSON (schedule, execute, cancel) for a single target + /// @param from The addresses of the sender for the schedule, execute, and cancel + /// @param target The address of the contract to call + /// @param value The value to send with the call + /// @param data The encoded target method call + /// @param delay The delay for the access manager operation. 0 is minimum delay + function _generateAction( + address[] memory from, + address target, + uint256 value, + bytes memory data, + uint256 delay + ) internal { + _scheduleAction(from[0], target, value, data, delay); + _executeAction(from[1], target, value, data); + _cancelAction(from[2], from[0], target, value, data); + } + + /// @notice Encodes the call to AccessManager.schedule + /// @param from The address of the sender + /// @param target The address of the contract to call + /// @param value The value to send with the call + /// @param data The encoded target method call + /// @param delay The delay for the access manager operation. Must be >= minDelay + function _scheduleAction( + address from, + address target, + uint256 value, + bytes memory data, + uint256 delay + ) internal { + bytes memory _txData = abi.encodeWithSelector( + AccessManager.schedule.selector, + target, + data, + uint48(0) + ); + _saveTx(Operation.SCHEDULE, from, address(protocolAccessManager), value, _txData, string.concat(action, "-schedule")); + } + + /// @notice Encodes the call to AccessManager.execute + /// @param target The address of the contract to call + /// @param value The value to send with the call + /// @param data The encoded target method call + function _executeAction( + address from, + address target, + uint256 value, + bytes memory data + ) internal { + bytes memory _txData = abi.encodeWithSelector( + AccessManager.execute.selector, + target, + data + ); + _saveTx(Operation.EXECUTE, from, address(protocolAccessManager), value, _txData, string.concat(action, "-execute")); + } + + /// @notice Encodes the call to AccessManager.cancel + /// @param target The address of the contract to call + /// @param value The value sent to scheduled call + /// @param data The encoded target method call + function _cancelAction( + address from, + address scheduleCaller, + address target, + uint256 value, + bytes memory data + ) internal { + bytes memory _txData = abi.encodeWithSelector( + AccessManager.cancel.selector, + scheduleCaller, + target, + data + ); + _saveTx(Operation.CANCEL, from, address(protocolAccessManager), value, _txData, string.concat(action, "-cancel")); + } + + /// @notice Encodes regular txs + /// @param from The address of the sender + /// @param txData The encoded target method call + function _generateRegularTx( + address from, + bytes memory txData + ) internal { + _saveTx(Operation.REGULAR_TX, from, address(protocolAccessManager), 0, txData, string.concat(action, "-regular")); + } +} \ No newline at end of file diff --git a/script/foundry/utils/JSONTxWriter.s.sol b/script/foundry/utils/JSONTxWriter.s.sol new file mode 100644 index 00000000..b4839e32 --- /dev/null +++ b/script/foundry/utils/JSONTxWriter.s.sol @@ -0,0 +1,178 @@ +/* solhint-disable no-console */ +/* solhint-disable quotes */ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { Script } from "forge-std/Script.sol"; +import { stdJson } from "forge-std/StdJson.sol"; +import { console2 } from "forge-std/console2.sol"; + +import { StringUtil } from "./StringUtil.sol"; + +/// @title JSONTxWriter +/// @notice Writes the tx json files for the access manager operations +contract JSONTxWriter is Script { + using StringUtil for uint256; + using stdJson for string; + + enum Operation { + SCHEDULE, + EXECUTE, + CANCEL, + REGULAR_TX // Usually calls directly to the access manager, like renounce roles + } + + bool isUnitTest; + bool isAeneidTest; + + /// @notice A struct to store the transaction details + /// @param from The address of the sender + /// @param to The address of the contract to call + /// @param value The value to send with the call + /// @param data The encoded target method call + /// @param operation Needed for Safe. 0 is call, 1 is delegatecall + /// @param comment The comment for the transaction + struct Transaction { + address from; + address to; + uint256 value; + bytes data; + uint8 operation; + string comment; + } + + /// @notice A mapping to store the transactions to batch for each access manager operation + mapping(Operation => Transaction[]) public transactions; + + /// @notice The chain id + string private chainId; + + /// @notice The action name + string internal action; + + constructor() { + chainId = (block.chainid).toString(); + } + + function setAction(string memory _action) internal { + action = _action; + } + + function setIsTest(bool _isUnitTest, bool _isAeneidTest) internal { + isUnitTest = _isUnitTest; + isAeneidTest = _isAeneidTest; + } + + /// @notice Saves a transaction to the mapping + /// @param _accessManagerOp The access manager operation + /// @param _from The address of the sender + /// @param _to The address of the contract to call + /// @param _value The value to send with the call + /// @param _data The encoded target method call + /// @param _comment The comment for the transaction + function _saveTx( + Operation _accessManagerOp, + address _from, + address _to, + uint256 _value, + bytes memory _data, + string memory _comment + ) internal { + transactions[_accessManagerOp].push( + Transaction({ from: _from, to: _to, value: _value, data: _data, operation: 0, comment: _comment }) + ); + console2.log("Added tx ", uint8(_accessManagerOp)); + console2.log("To: ", _to); + console2.log("Value: ", _value); + console2.log("Data: "); + console2.logBytes(_data); + console2.log("Operation: 0"); + console2.log("Comment: ", _comment); + } + + /// @notice Writes all the tx json files for the access manager operations + function _writeFiles() internal { + console2.log("Writing txs to file"); + Transaction[] memory _transactions = transactions[Operation.SCHEDULE]; + console2.log("Schedule txs: ", _transactions.length); + if (_transactions.length > 0) { + _writeTxArrayToJson(Operation.SCHEDULE, _transactions); + } + + _transactions = transactions[Operation.EXECUTE]; + console2.log("Execute txs: ", _transactions.length); + if (_transactions.length > 0) { + _writeTxArrayToJson(Operation.EXECUTE, _transactions); + } + + _transactions = transactions[Operation.CANCEL]; + console2.log("Cancel txs: ", _transactions.length); + if (_transactions.length > 0) { + _writeTxArrayToJson(Operation.CANCEL, _transactions); + } + + _transactions = transactions[Operation.REGULAR_TX]; + console2.log("Regular txs: ", _transactions.length); + if (_transactions.length > 0) { + _writeTxArrayToJson(Operation.REGULAR_TX, _transactions); + } + } + + /// @notice Writes a json files for the access manager operations + /// @param _accessManagerOp The access manager operation + /// @param txArray The transactions to write to the json file + function _writeTxArrayToJson(Operation _accessManagerOp, Transaction[] memory txArray) internal { + string memory json = "["; + for (uint i = 0; i < txArray.length; i++) { + if (i > 0) { + json = string(abi.encodePacked(json, ",")); + } + json = string(abi.encodePacked(json, "{")); + json = string(abi.encodePacked(json, '"from":"', vm.toString(txArray[i].from), '",')); + json = string(abi.encodePacked(json, '"to":"', vm.toString(txArray[i].to), '",')); + json = string(abi.encodePacked(json, '"value":', vm.toString(txArray[i].value), ",")); + json = string(abi.encodePacked(json, '"data":"', vm.toString(txArray[i].data), '",')); + json = string(abi.encodePacked(json, '"operation":', vm.toString(txArray[i].operation), ",")); + json = string(abi.encodePacked(json, '"comment":"', txArray[i].comment, '"')); + json = string(abi.encodePacked(json, "}")); + } + json = string(abi.encodePacked(json, "]")); + + string memory outputDir; + if (!isUnitTest) { + outputDir = isAeneidTest ? "./script/foundry/admin-actions/output/aeneid-test/" : "./script/foundry/admin-actions/output/"; + } else { + outputDir = isAeneidTest ? "./script/foundry/admin-actions/output-test/aeneid-test/" : "./script/foundry/admin-actions/output-test/"; + } + + string memory filename = string( + abi.encodePacked( + outputDir, + chainId, + "/", + action, + "-", + _accessManagerOpToString(_accessManagerOp), + ".json" + ) + ); + vm.writeFile(filename, json); + console2.log("Wrote batch txs to ", filename); + } + + /// @notice Converts the access manager operation to a string + /// @param _accessManagerOp The access manager operation + /// @return The string representation of the access manager operation + function _accessManagerOpToString(Operation _accessManagerOp) internal pure returns (string memory) { + if (_accessManagerOp == Operation.SCHEDULE) { + return "schedule"; + } else if (_accessManagerOp == Operation.EXECUTE) { + return "execute"; + } else if (_accessManagerOp == Operation.CANCEL) { + return "cancel"; + } else if (_accessManagerOp == Operation.REGULAR_TX) { + return "regular"; + } + revert("Invalid operation"); + } +} \ No newline at end of file diff --git a/test/foundry/migrate-to-safe/GrantRolesToSafe.t.sol b/test/foundry/migrate-to-safe/GrantRolesToSafe.t.sol new file mode 100644 index 00000000..b13a485d --- /dev/null +++ b/test/foundry/migrate-to-safe/GrantRolesToSafe.t.sol @@ -0,0 +1,717 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.26; + +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; + +import { GrantRolesToSafe } from "../../../script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol"; +import { JSONTxWriter } from "../../../script/foundry/utils/JSONTxWriter.s.sol"; + +import { stdJson } from "forge-std/StdJson.sol"; +import { BaseTest } from "test/foundry/utils/BaseTest.t.sol"; +// solhint-disable-next-line +import { console2 } from "forge-std/console2.sol"; + +contract GrantRolesToSafeTest is BaseTest { + // Maximum number of transactions in JSON files + uint256 public constant MAX_TXS_PER_JSON = 1000; + + string public constant OUTPUT_DIR = "./script/foundry/admin-actions/output-test/"; + + uint64 public constant ADMIN_ROLE_ID = 0; + uint64 public constant UPGRADER_ROLE_ID = 1; + uint64 public constant PAUSE_ROLE_ID = 2; + uint64 public constant GUARDIAN_ROLE_ID = 3; + + uint256 public delayMainnet; + address public oldAdminMainnet; + address public oldUpgraderMainnet; + address public oldPauseAdmin1Mainnet; + address public oldPauseAdmin2Mainnet; + address public oldGuardianMainnet; + + uint256 public delayAeneid; + address public oldAdminAeneid; + address public oldUpgraderAeneid; + address public oldPauseAdmin1Aeneid; + address public oldPauseAdmin2Aeneid; + address public oldGuardianAeneid; + + address public governanceSafeMultisigMainnet; + address public securityCouncilSafeMultisigMainnet; + address public governanceSafeMultisigAeneid; + address public securityCouncilSafeMultisigAeneid; + + function setUp() public override { + // Mainnet + delayMainnet = 5 days; + oldAdminMainnet = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldUpgraderMainnet = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldPauseAdmin1Mainnet = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2Mainnet = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldGuardianMainnet = 0x76430daA671BE12200Cd424Ea6bdd8129A769033; + governanceSafeMultisigMainnet = 0xF07cA4b61022F0399C1511E7E668A57567f2138B; + securityCouncilSafeMultisigMainnet = 0x25D2605b2C768082A14E79713114389d0eC297D8; + + // Aeneid + delayAeneid = 10 minutes; + oldAdminAeneid = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldUpgraderAeneid = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldPauseAdmin1Aeneid = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2Aeneid = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldGuardianAeneid = address(0); + governanceSafeMultisigAeneid = 0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524; + securityCouncilSafeMultisigAeneid = 0xC9a862Df1872402c4eAcbb8402F9BE628B52d270; + } + + function test_GrantRoles_Mainnet_Success() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork mainnet + uint256 forkId = vm.createFork("https://mainnet.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigMainnet, securityCouncilSafeMultisigMainnet, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe", false); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + + skip(delayMainnet + 1); + + (bool hasRoleSafeAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeUpgradeBefore, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigMainnet + ); + (bool hasRoleSafePauseBefore, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeGuardianBefore, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigMainnet + ); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + skip(delayMainnet + 1); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigMainnet + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigMainnet + ); + + assertEq(hasRoleSafeAdminBefore, false); + assertEq(hasRoleSafeUpgradeBefore, false); + assertEq(hasRoleSafePauseBefore, false); + assertEq(hasRoleSafeGuardianBefore, false); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + function test_GrantRoles_Mainnet_Cancel() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork mainnet + uint256 forkId = vm.createFork("https://mainnet.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigMainnet, securityCouncilSafeMultisigMainnet, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe", false); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert cancelTxs to bytes array for multicall + bytes[] memory cancelCalls = new bytes[](cancelTxs.length); + for (uint256 i = 0; i < cancelTxs.length; i++) { + cancelCalls[i] = cancelTxs[i].data; + } + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + vm.stopPrank(); + + (bool hasRoleSafeAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeUpgradeBefore, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigMainnet + ); + (bool hasRoleSafePauseBefore, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeGuardianBefore, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigMainnet + ); + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(cancelCalls); + vm.stopPrank(); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigMainnet + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigMainnet + ); + + assertEq(hasRoleSafeAdminBefore, false); + assertEq(hasRoleSafeUpgradeBefore, false); + assertEq(hasRoleSafePauseBefore, false); + assertEq(hasRoleSafeGuardianBefore, false); + + assertEq(hasRoleSafeAdminAfter, false); + assertEq(hasRoleSafeUpgradeAfter, false); + assertEq(hasRoleSafePauseAfter, false); + assertEq(hasRoleSafeGuardianAfter, false); + } + + function test_GrantRoles_Aeneid_Success() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork aeneid + uint256 forkId = vm.createFork("https://aeneid.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe", false); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + vm.startPrank(oldAdminAeneid); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeBefore, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseBefore, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianBefore, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + assertEq(hasRoleSafeAdminBefore, false); + assertEq(hasRoleSafeUpgradeBefore, false); + assertEq(hasRoleSafePauseBefore, false); + assertEq(hasRoleSafeGuardianBefore, false); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + function test_GrantRoles_Aeneid_Cancel() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork aeneid + uint256 forkId = vm.createFork("https://aeneid.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe", false); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert cancelTxs to bytes array for multicall + bytes[] memory cancelCalls = new bytes[](cancelTxs.length); + for (uint256 i = 0; i < cancelTxs.length; i++) { + cancelCalls[i] = cancelTxs[i].data; + } + + vm.startPrank(oldAdminAeneid); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeBefore, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseBefore, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianBefore, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + Multicall(address(protocolAccessManager)).multicall(cancelCalls); + + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + assertEq(hasRoleSafeAdminBefore, false); + assertEq(hasRoleSafeUpgradeBefore, false); + assertEq(hasRoleSafePauseBefore, false); + assertEq(hasRoleSafeGuardianBefore, false); + + assertEq(hasRoleSafeAdminAfter, false); + assertEq(hasRoleSafeUpgradeAfter, false); + assertEq(hasRoleSafePauseAfter, false); + assertEq(hasRoleSafeGuardianAfter, false); + } + + function test_GrantRoles_AeneidTestDeployment_Success() public { + protocolAccessManager = AccessManager(0x7fc3eD9B2CC14C0872ec633c6CC290b8B9B3AA5A); + // Fork aeneid + uint256 forkId = vm.createFork("https://aeneid.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, true); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe", true); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeBefore, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseBefore, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianBefore, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + assertEq(hasRoleSafeAdminBefore, false); + assertEq(hasRoleSafeUpgradeBefore, false); + assertEq(hasRoleSafePauseBefore, false); + assertEq(hasRoleSafeGuardianBefore, false); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + function test_GrantRoles_AeneidTestDeployment_Cancel() public { + protocolAccessManager = AccessManager(0x7fc3eD9B2CC14C0872ec633c6CC290b8B9B3AA5A); + // Fork aeneid + uint256 forkId = vm.createFork("https://aeneid.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, true); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe", true); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert cancelTxs to bytes array for multicall + bytes[] memory cancelCalls = new bytes[](cancelTxs.length); + for (uint256 i = 0; i < cancelTxs.length; i++) { + cancelCalls[i] = cancelTxs[i].data; + } + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeBefore, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseBefore, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianBefore, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + Multicall(address(protocolAccessManager)).multicall(cancelCalls); + + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + assertEq(hasRoleSafeAdminBefore, false); + assertEq(hasRoleSafeUpgradeBefore, false); + assertEq(hasRoleSafePauseBefore, false); + assertEq(hasRoleSafeGuardianBefore, false); + + assertEq(hasRoleSafeAdminAfter, false); + assertEq(hasRoleSafeUpgradeAfter, false); + assertEq(hasRoleSafePauseAfter, false); + assertEq(hasRoleSafeGuardianAfter, false); + } + + function test_GrantRoles_AeneidTestDeployment_Reschedule() public { + protocolAccessManager = AccessManager(0x7fc3eD9B2CC14C0872ec633c6CC290b8B9B3AA5A); + // Fork aeneid + uint256 forkId = vm.createFork("https://aeneid.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, true); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe", true); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + // Convert cancelTxs to bytes array for multicall + bytes[] memory cancelCalls = new bytes[](cancelTxs.length); + for (uint256 i = 0; i < cancelTxs.length; i++) { + cancelCalls[i] = cancelTxs[i].data; + } + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delayAeneid + 1); + Multicall(address(protocolAccessManager)).multicall(cancelCalls); + // skip(delayAeneid + 1); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeBefore, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseBefore, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianBefore, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + skip(delayAeneid + 1); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + assertEq(hasRoleSafeAdminBefore, false); + assertEq(hasRoleSafeUpgradeBefore, false); + assertEq(hasRoleSafePauseBefore, false); + assertEq(hasRoleSafeGuardianBefore, false); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + /** + * @notice Execute a single transaction + * @param transaction The transaction to execute + */ + function _rawTransaction(JSONTxWriter.Transaction memory transaction) internal { + vm.startPrank(transaction.from); + (bool success, ) = transaction.to.call{ value: transaction.value }(transaction.data); + require(success, "Transaction execution failed"); + vm.stopPrank(); + } + + /** + * @notice Read transactions from regular JSON files + * @param baseFilename The base filename without suffix (-regular) + * @return regularTxs Transaction struct from regular file + */ + function _readRegularTransactionFiles( + string memory baseFilename + ) internal returns (JSONTxWriter.Transaction[] memory regularTxs) { + // Create paths for all three file types + string memory basePath = string.concat(OUTPUT_DIR, vm.toString(block.chainid), "/"); + string memory regularPath = string.concat(basePath, baseFilename, "-regular.json"); + + // Read regular transaction + assertTrue(vm.exists(regularPath), "Regular JSON file not found"); + string memory regularJson = vm.readFile(regularPath); + JSONTxWriter.Transaction[] memory regularTxs = _parseTransactionsFromJson(regularJson); + + return (regularTxs); + } + + /** + * @notice Read transactions from schedule, cancel, and execute JSON files + * @param baseFilename The base filename without suffix (-schedule, -cancel, -execute) + * @param isAeneidTest Whether the test is for Aeneid test deployment + * @return scheduleTxs Transaction struct from schedule file + * @return executeTxs Transaction struct from execute file + * @return cancelTxs Transaction struct from cancel file + */ + function _readNonRegularTransactionFiles( + string memory baseFilename, + bool isAeneidTest + ) + internal + returns ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) + { + // Create paths for all three file types + string memory outputDir = isAeneidTest ? "./script/foundry/admin-actions/output-test/aeneid-test/" : OUTPUT_DIR; + string memory basePath = string.concat(outputDir, vm.toString(block.chainid), "/"); + string memory schedulePath = string.concat(basePath, baseFilename, "-schedule.json"); + string memory cancelPath = string.concat(basePath, baseFilename, "-cancel.json"); + string memory executePath = string.concat(basePath, baseFilename, "-execute.json"); + + // Read schedule transaction + assertTrue(vm.exists(schedulePath), "Schedule JSON file not found"); + string memory scheduleJson = vm.readFile(schedulePath); + JSONTxWriter.Transaction[] memory scheduleTxs = _parseTransactionsFromJson(scheduleJson); + + // Read cancel transaction + assertTrue(vm.exists(cancelPath), "Cancel JSON file not found"); + string memory cancelJson = vm.readFile(cancelPath); + JSONTxWriter.Transaction[] memory cancelTxs = _parseTransactionsFromJson(cancelJson); + + // Read execute transaction + assertTrue(vm.exists(executePath), "Execute JSON file not found"); + string memory executeJson = vm.readFile(executePath); + JSONTxWriter.Transaction[] memory executeTxs = _parseTransactionsFromJson(executeJson); + + return (scheduleTxs, executeTxs, cancelTxs); + } + + /** + * @notice Parse a JSON string into an array of Transaction structs + * @param json The JSON string to parse + * @return An array of Transaction structs + */ + function _parseTransactionsFromJson(string memory json) internal view returns (JSONTxWriter.Transaction[] memory) { + // Get the number of transactions in the JSON array + // Create an array to store the transactions + JSONTxWriter.Transaction[] memory readTxs = new JSONTxWriter.Transaction[](MAX_TXS_PER_JSON); + uint256 effectiveTxs = 0; + // Parse each transaction in the array + for (uint256 i = 0; i < MAX_TXS_PER_JSON; i++) { + try this._parseTransaction(json, i) returns (JSONTxWriter.Transaction memory transaction) { + readTxs[i] = transaction; + effectiveTxs++; + } catch { + // solhint-disable-next-line + console2.log("No more transactions in JSON"); + break; + } + } + + JSONTxWriter.Transaction[] memory transactions = new JSONTxWriter.Transaction[](effectiveTxs); + for (uint256 i = 0; i < effectiveTxs; i++) { + transactions[i] = readTxs[i]; + } + return transactions; + } + + function _parseTransaction( + string memory json, + uint256 index + ) external pure returns (JSONTxWriter.Transaction memory transaction) { + string memory indexPath = string.concat("[", vm.toString(index), "]"); + + address from = stdJson.readAddress(json, string.concat(indexPath, ".from")); + address to = stdJson.readAddress(json, string.concat(indexPath, ".to")); + uint256 value = stdJson.readUint(json, string.concat(indexPath, ".value")); + bytes memory data = stdJson.readBytes(json, string.concat(indexPath, ".data")); + uint8 operation = uint8(stdJson.readUint(json, string.concat(indexPath, ".operation"))); + string memory comment = stdJson.readString(json, string.concat(indexPath, ".comment")); + + // Create the transaction struct + return + JSONTxWriter.Transaction({ + from: from, + to: to, + value: value, + data: data, + operation: operation, + comment: comment + }); + } +} diff --git a/test/foundry/migrate-to-safe/RemoveRolesFromNonSafe.t.sol b/test/foundry/migrate-to-safe/RemoveRolesFromNonSafe.t.sol new file mode 100644 index 00000000..816f7550 --- /dev/null +++ b/test/foundry/migrate-to-safe/RemoveRolesFromNonSafe.t.sol @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.26; + +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; + +import { GrantRolesToSafe } from "../../../script/foundry/migrate-to-safe/1.GrantRolesToSafe.s.sol"; +import { RemoveRolesFromNonSafe } from "../../../script/foundry/migrate-to-safe/2.RemoveRolesFromNonSafe.s.sol"; +import { JSONTxWriter } from "../../../script/foundry/utils/JSONTxWriter.s.sol"; + +import { stdJson } from "forge-std/StdJson.sol"; +import { BaseTest } from "test/foundry/utils/BaseTest.t.sol"; +// solhint-disable-next-line +import { console2 } from "forge-std/console2.sol"; + +contract GrantRolesToSafeTest is BaseTest { + // Maximum number of transactions in JSON files + uint256 public constant MAX_TXS_PER_JSON = 1000; + + string public constant OUTPUT_DIR = "./script/foundry/admin-actions/output-test/"; + + uint64 public constant ADMIN_ROLE_ID = 0; + uint64 public constant UPGRADER_ROLE_ID = 1; + uint64 public constant PAUSE_ROLE_ID = 2; + uint64 public constant GUARDIAN_ROLE_ID = 3; + + uint256 public delayMainnet; + address public oldAdminMainnet; + address public oldUpgraderMainnet; + address public oldPauseAdmin1Mainnet; + address public oldPauseAdmin2Mainnet; + address public oldGuardianMainnet; + + uint256 public delayAeneid; + address public oldAdminAeneid; + address public oldUpgraderAeneid; + address public oldPauseAdmin1Aeneid; + address public oldPauseAdmin2Aeneid; + address public oldGuardianAeneid; + + address public governanceSafeMultisigMainnet; + address public securityCouncilSafeMultisigMainnet; + address public governanceSafeMultisigAeneid; + address public securityCouncilSafeMultisigAeneid; + + function setUp() public override { + // Mainnet + delayMainnet = 5 days; + oldAdminMainnet = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldUpgraderMainnet = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldPauseAdmin1Mainnet = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2Mainnet = 0x4C30baDa479D0e13300b31b1696A5E570848bbEe; + oldGuardianMainnet = 0x76430daA671BE12200Cd424Ea6bdd8129A769033; + governanceSafeMultisigMainnet = address(1); + securityCouncilSafeMultisigMainnet = address(2); + + // Aeneid + delayAeneid = 10 minutes; + oldAdminAeneid = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldUpgraderAeneid = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldPauseAdmin1Aeneid = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + oldPauseAdmin2Aeneid = 0xe83F899BD5790e1be9b6B51ffcF32b3b2b1F5a9e; + oldGuardianAeneid = address(0); + governanceSafeMultisigAeneid = address(3); + securityCouncilSafeMultisigAeneid = address(4); + } + + function test_RemoveRoles_Mainnet_Success() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork mainnet + uint256 forkId = vm.createFork("https://mainnet.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigMainnet, securityCouncilSafeMultisigMainnet, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe"); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + + skip(delayMainnet + 1); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + vm.stopPrank(); + + skip(delayMainnet + 1); + + RemoveRolesFromNonSafe deployScript2 = new RemoveRolesFromNonSafe(); + deployScript2.run(governanceSafeMultisigMainnet, securityCouncilSafeMultisigMainnet, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs2, + JSONTxWriter.Transaction[] memory executeTxs2, + JSONTxWriter.Transaction[] memory cancelTxs2 + ) = _readNonRegularTransactionFiles("remove-roles-from-non-safe"); + + assertEq(scheduleTxs2.length, 5); + assertEq(executeTxs2.length, 5); + assertEq(cancelTxs2.length, 5); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls2 = new bytes[](scheduleTxs2.length); + for (uint256 i = 0; i < scheduleTxs2.length; i++) { + scheduleCalls2[i] = scheduleTxs2[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls2 = new bytes[](executeTxs2.length); + for (uint256 i = 0; i < executeTxs2.length; i++) { + executeCalls2[i] = executeTxs2[i].data; + } + + vm.startPrank(governanceSafeMultisigMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls2); + + skip(delayMainnet + 1); + + (bool hasRoleOldAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminMainnet); + (bool hasRoleOldUpgraderBefore, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderMainnet); + (bool hasRoleOldPauseAdmin1Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Mainnet); + (bool hasRoleOldPauseAdmin2Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Mainnet); + (bool hasRoleOldGuardianBefore, ) = protocolAccessManager.hasRole(GUARDIAN_ROLE_ID, oldGuardianMainnet); + + Multicall(address(protocolAccessManager)).multicall(executeCalls2); + + skip(delayMainnet + 1); + + (bool hasRoleOldAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminMainnet); + (bool hasRoleOldUpgraderAfter, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderMainnet); + (bool hasRoleOldPauseAdmin1After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Mainnet); + (bool hasRoleOldPauseAdmin2After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Mainnet); + (bool hasRoleOldGuardianAfter, ) = protocolAccessManager.hasRole(GUARDIAN_ROLE_ID, oldGuardianMainnet); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigMainnet + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigMainnet + ); + + assertEq(hasRoleOldAdminBefore, true); + assertEq(hasRoleOldUpgraderBefore, true); + assertEq(hasRoleOldPauseAdmin1Before, true); + assertEq(hasRoleOldPauseAdmin2Before, true); + assertEq(hasRoleOldGuardianBefore, true); + + assertEq(hasRoleOldAdminAfter, false); + assertEq(hasRoleOldUpgraderAfter, false); + assertEq(hasRoleOldPauseAdmin1After, false); + assertEq(hasRoleOldPauseAdmin2After, false); + assertEq(hasRoleOldGuardianAfter, false); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + function test_RemoveRoles_Mainnet_Cancel() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork mainnet + uint256 forkId = vm.createFork("https://mainnet.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigMainnet, securityCouncilSafeMultisigMainnet, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe"); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + vm.startPrank(oldAdminMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + + skip(delayMainnet + 1); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + vm.stopPrank(); + + skip(delayMainnet + 1); + + RemoveRolesFromNonSafe deployScript2 = new RemoveRolesFromNonSafe(); + deployScript2.run(governanceSafeMultisigMainnet, securityCouncilSafeMultisigMainnet, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs2, + JSONTxWriter.Transaction[] memory executeTxs2, + JSONTxWriter.Transaction[] memory cancelTxs2 + ) = _readNonRegularTransactionFiles("remove-roles-from-non-safe"); + + assertEq(scheduleTxs2.length, 5); + assertEq(executeTxs2.length, 5); + assertEq(cancelTxs2.length, 5); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls2 = new bytes[](scheduleTxs2.length); + for (uint256 i = 0; i < scheduleTxs2.length; i++) { + scheduleCalls2[i] = scheduleTxs2[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory cancelCalls2 = new bytes[](cancelTxs2.length); + for (uint256 i = 0; i < cancelTxs2.length; i++) { + cancelCalls2[i] = cancelTxs2[i].data; + } + + vm.startPrank(governanceSafeMultisigMainnet); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls2); + + skip(delayMainnet + 1); + + (bool hasRoleOldAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminMainnet); + (bool hasRoleOldUpgraderBefore, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderMainnet); + (bool hasRoleOldPauseAdmin1Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Mainnet); + (bool hasRoleOldPauseAdmin2Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Mainnet); + (bool hasRoleOldGuardianBefore, ) = protocolAccessManager.hasRole(GUARDIAN_ROLE_ID, oldGuardianMainnet); + + Multicall(address(protocolAccessManager)).multicall(cancelCalls2); + + skip(delayMainnet + 1); + + (bool hasRoleOldAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminMainnet); + (bool hasRoleOldUpgraderAfter, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderMainnet); + (bool hasRoleOldPauseAdmin1After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Mainnet); + (bool hasRoleOldPauseAdmin2After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Mainnet); + (bool hasRoleOldGuardianAfter, ) = protocolAccessManager.hasRole(GUARDIAN_ROLE_ID, oldGuardianMainnet); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigMainnet + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigMainnet); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigMainnet + ); + + assertEq(hasRoleOldAdminBefore, true); + assertEq(hasRoleOldUpgraderBefore, true); + assertEq(hasRoleOldPauseAdmin1Before, true); + assertEq(hasRoleOldPauseAdmin2Before, true); + assertEq(hasRoleOldGuardianBefore, true); + + assertEq(hasRoleOldAdminAfter, true); + assertEq(hasRoleOldUpgraderAfter, true); + assertEq(hasRoleOldPauseAdmin1After, true); + assertEq(hasRoleOldPauseAdmin2After, true); + assertEq(hasRoleOldGuardianAfter, true); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + function test_RemoveRoles_Aeneid_Success() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork aeneid + uint256 forkId = vm.createFork("https://aeneid.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe"); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + vm.startPrank(oldAdminAeneid); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + + skip(delayAeneid + 1); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + vm.stopPrank(); + + skip(delayAeneid + 1); + + RemoveRolesFromNonSafe deployScript2 = new RemoveRolesFromNonSafe(); + deployScript2.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs2, + JSONTxWriter.Transaction[] memory executeTxs2, + JSONTxWriter.Transaction[] memory cancelTxs2 + ) = _readNonRegularTransactionFiles("remove-roles-from-non-safe"); + + assertEq(scheduleTxs2.length, 4); + assertEq(executeTxs2.length, 4); + assertEq(cancelTxs2.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls2 = new bytes[](scheduleTxs2.length); + for (uint256 i = 0; i < scheduleTxs2.length; i++) { + scheduleCalls2[i] = scheduleTxs2[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls2 = new bytes[](executeTxs2.length); + for (uint256 i = 0; i < executeTxs2.length; i++) { + executeCalls2[i] = executeTxs2[i].data; + } + + vm.startPrank(governanceSafeMultisigAeneid); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls2); + vm.stopPrank(); + + skip(delayAeneid + 1); + + (bool hasRoleOldAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminAeneid); + (bool hasRoleOldUpgraderBefore, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderAeneid); + (bool hasRoleOldPauseAdmin1Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Aeneid); + (bool hasRoleOldPauseAdmin2Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Aeneid); + + vm.startPrank(governanceSafeMultisigAeneid); + Multicall(address(protocolAccessManager)).multicall(executeCalls2); + vm.stopPrank(); + + skip(delayAeneid + 1); + + (bool hasRoleOldAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminAeneid); + (bool hasRoleOldUpgraderAfter, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderAeneid); + (bool hasRoleOldPauseAdmin1After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Aeneid); + (bool hasRoleOldPauseAdmin2After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Aeneid); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + assertEq(hasRoleOldAdminBefore, true); + assertEq(hasRoleOldUpgraderBefore, true); + assertEq(hasRoleOldPauseAdmin1Before, true); + assertEq(hasRoleOldPauseAdmin2Before, true); + + assertEq(hasRoleOldAdminAfter, false); + assertEq(hasRoleOldUpgraderAfter, false); + assertEq(hasRoleOldPauseAdmin1After, false); + assertEq(hasRoleOldPauseAdmin2After, false); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + function test_RemoveRoles_Aeneid_Cancel() public { + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + // Fork aeneid + uint256 forkId = vm.createFork("https://aeneid.storyrpc.io/"); + vm.selectFork(forkId); + + GrantRolesToSafe deployScript = new GrantRolesToSafe(); + deployScript.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-roles-to-safe"); + + assertEq(scheduleTxs.length, 4); + assertEq(executeTxs.length, 4); + assertEq(cancelTxs.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + bytes[] memory executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + vm.startPrank(oldAdminAeneid); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + + skip(delayAeneid + 1); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + vm.stopPrank(); + + skip(delayAeneid + 1); + + RemoveRolesFromNonSafe deployScript2 = new RemoveRolesFromNonSafe(); + deployScript2.run(governanceSafeMultisigAeneid, securityCouncilSafeMultisigAeneid, true, false); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs2, + JSONTxWriter.Transaction[] memory executeTxs2, + JSONTxWriter.Transaction[] memory cancelTxs2 + ) = _readNonRegularTransactionFiles("remove-roles-from-non-safe"); + + assertEq(scheduleTxs2.length, 4); + assertEq(executeTxs2.length, 4); + assertEq(cancelTxs2.length, 4); + + // Convert scheduleTxs to bytes array for multicall + bytes[] memory scheduleCalls2 = new bytes[](scheduleTxs2.length); + for (uint256 i = 0; i < scheduleTxs2.length; i++) { + scheduleCalls2[i] = scheduleTxs2[i].data; + } + + // Convert cancelTxs to bytes array for multicall + bytes[] memory cancelCalls2 = new bytes[](cancelTxs2.length); + for (uint256 i = 0; i < cancelTxs2.length; i++) { + cancelCalls2[i] = cancelTxs2[i].data; + } + + vm.startPrank(governanceSafeMultisigAeneid); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls2); + + skip(delayAeneid + 1); + + (bool hasRoleOldAdminBefore, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminAeneid); + (bool hasRoleOldUpgraderBefore, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderAeneid); + (bool hasRoleOldPauseAdmin1Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Aeneid); + (bool hasRoleOldPauseAdmin2Before, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Aeneid); + + Multicall(address(protocolAccessManager)).multicall(cancelCalls2); + vm.stopPrank(); + + skip(delayAeneid + 1); + + (bool hasRoleOldAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, oldAdminAeneid); + (bool hasRoleOldUpgraderAfter, ) = protocolAccessManager.hasRole(UPGRADER_ROLE_ID, oldUpgraderAeneid); + (bool hasRoleOldPauseAdmin1After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin1Aeneid); + (bool hasRoleOldPauseAdmin2After, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, oldPauseAdmin2Aeneid); + + (bool hasRoleSafeAdminAfter, ) = protocolAccessManager.hasRole(ADMIN_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeUpgradeAfter, ) = protocolAccessManager.hasRole( + UPGRADER_ROLE_ID, + governanceSafeMultisigAeneid + ); + (bool hasRoleSafePauseAfter, ) = protocolAccessManager.hasRole(PAUSE_ROLE_ID, governanceSafeMultisigAeneid); + (bool hasRoleSafeGuardianAfter, ) = protocolAccessManager.hasRole( + GUARDIAN_ROLE_ID, + securityCouncilSafeMultisigAeneid + ); + + assertEq(hasRoleOldAdminBefore, true); + assertEq(hasRoleOldUpgraderBefore, true); + assertEq(hasRoleOldPauseAdmin1Before, true); + assertEq(hasRoleOldPauseAdmin2Before, true); + + assertEq(hasRoleOldAdminAfter, true); + assertEq(hasRoleOldUpgraderAfter, true); + assertEq(hasRoleOldPauseAdmin1After, true); + assertEq(hasRoleOldPauseAdmin2After, true); + + assertEq(hasRoleSafeAdminAfter, true); + assertEq(hasRoleSafeUpgradeAfter, true); + assertEq(hasRoleSafePauseAfter, true); + assertEq(hasRoleSafeGuardianAfter, true); + } + + /** + * @notice Execute a single transaction + * @param transaction The transaction to execute + */ + function _rawTransaction(JSONTxWriter.Transaction memory transaction) internal { + vm.startPrank(transaction.from); + (bool success, ) = transaction.to.call{ value: transaction.value }(transaction.data); + require(success, "Transaction execution failed"); + vm.stopPrank(); + } + + /** + * @notice Read transactions from regular JSON files + * @param baseFilename The base filename without suffix (-regular) + * @return regularTxs Transaction struct from regular file + */ + function _readRegularTransactionFiles( + string memory baseFilename + ) internal returns (JSONTxWriter.Transaction[] memory regularTxs) { + // Create paths for all three file types + string memory basePath = string.concat(OUTPUT_DIR, vm.toString(block.chainid), "/"); + string memory regularPath = string.concat(basePath, baseFilename, "-regular.json"); + + // Read regular transaction + assertTrue(vm.exists(regularPath), "Regular JSON file not found"); + string memory regularJson = vm.readFile(regularPath); + JSONTxWriter.Transaction[] memory regularTxs = _parseTransactionsFromJson(regularJson); + + return (regularTxs); + } + + /** + * @notice Read transactions from schedule, cancel, and execute JSON files + * @param baseFilename The base filename without suffix (-schedule, -cancel, -execute) + * @return scheduleTxs Transaction struct from schedule file + * @return executeTxs Transaction struct from execute file + * @return cancelTxs Transaction struct from cancel file + */ + function _readNonRegularTransactionFiles( + string memory baseFilename + ) + internal + returns ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) + { + // Create paths for all three file types + string memory basePath = string.concat(OUTPUT_DIR, vm.toString(block.chainid), "/"); + string memory schedulePath = string.concat(basePath, baseFilename, "-schedule.json"); + string memory cancelPath = string.concat(basePath, baseFilename, "-cancel.json"); + string memory executePath = string.concat(basePath, baseFilename, "-execute.json"); + + // Read schedule transaction + assertTrue(vm.exists(schedulePath), "Schedule JSON file not found"); + string memory scheduleJson = vm.readFile(schedulePath); + JSONTxWriter.Transaction[] memory scheduleTxs = _parseTransactionsFromJson(scheduleJson); + + // Read cancel transaction + assertTrue(vm.exists(cancelPath), "Cancel JSON file not found"); + string memory cancelJson = vm.readFile(cancelPath); + JSONTxWriter.Transaction[] memory cancelTxs = _parseTransactionsFromJson(cancelJson); + + // Read execute transaction + assertTrue(vm.exists(executePath), "Execute JSON file not found"); + string memory executeJson = vm.readFile(executePath); + JSONTxWriter.Transaction[] memory executeTxs = _parseTransactionsFromJson(executeJson); + + return (scheduleTxs, executeTxs, cancelTxs); + } + + /** + * @notice Parse a JSON string into an array of Transaction structs + * @param json The JSON string to parse + * @return An array of Transaction structs + */ + function _parseTransactionsFromJson(string memory json) internal view returns (JSONTxWriter.Transaction[] memory) { + // Get the number of transactions in the JSON array + // Create an array to store the transactions + JSONTxWriter.Transaction[] memory readTxs = new JSONTxWriter.Transaction[](MAX_TXS_PER_JSON); + uint256 effectiveTxs = 0; + // Parse each transaction in the array + for (uint256 i = 0; i < MAX_TXS_PER_JSON; i++) { + try this._parseTransaction(json, i) returns (JSONTxWriter.Transaction memory transaction) { + readTxs[i] = transaction; + effectiveTxs++; + } catch { + // solhint-disable-next-line + console2.log("No more transactions in JSON"); + break; + } + } + + JSONTxWriter.Transaction[] memory transactions = new JSONTxWriter.Transaction[](effectiveTxs); + for (uint256 i = 0; i < effectiveTxs; i++) { + transactions[i] = readTxs[i]; + } + return transactions; + } + + function _parseTransaction( + string memory json, + uint256 index + ) external pure returns (JSONTxWriter.Transaction memory transaction) { + string memory indexPath = string.concat("[", vm.toString(index), "]"); + + address from = stdJson.readAddress(json, string.concat(indexPath, ".from")); + address to = stdJson.readAddress(json, string.concat(indexPath, ".to")); + uint256 value = stdJson.readUint(json, string.concat(indexPath, ".value")); + bytes memory data = stdJson.readBytes(json, string.concat(indexPath, ".data")); + uint8 operation = uint8(stdJson.readUint(json, string.concat(indexPath, ".operation"))); + string memory comment = stdJson.readString(json, string.concat(indexPath, ".comment")); + + // Create the transaction struct + return + JSONTxWriter.Transaction({ + from: from, + to: to, + value: value, + data: data, + operation: operation, + comment: comment + }); + } +} diff --git a/test/foundry/new-admin-role/GrantNewAdminRole.t.sol b/test/foundry/new-admin-role/GrantNewAdminRole.t.sol new file mode 100644 index 00000000..6a033e3a --- /dev/null +++ b/test/foundry/new-admin-role/GrantNewAdminRole.t.sol @@ -0,0 +1,796 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.26; + +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; +import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; + +import { ProtocolAdmin } from "../../../contracts/lib/ProtocolAdmin.sol"; +import { GroupNFT } from "../../../contracts/GroupNFT.sol"; +import { LicenseToken } from "../../../contracts/LicenseToken.sol"; +import { IPGraphACL } from "../../../contracts/access/IPGraphACL.sol"; +import { DisputeModule } from "../../../contracts/modules/dispute/DisputeModule.sol"; +import { ArbitrationPolicyUMA } from "../../../contracts/modules/dispute/policies/UMA/ArbitrationPolicyUMA.sol"; +import { GroupingModule } from "../../../contracts/modules/grouping/GroupingModule.sol"; +import { RoyaltyModule } from "../../../contracts/modules/royalty/RoyaltyModule.sol"; +import { VaultController } from "../../../contracts/modules/royalty/policies/VaultController.sol"; +import { ProtocolPauseAdmin } from "../../../contracts/pause/ProtocolPauseAdmin.sol"; +import { IPAssetRegistry } from "../../../contracts/registries/IPAssetRegistry.sol"; +import { LicenseRegistry } from "../../../contracts/registries/LicenseRegistry.sol"; +import { ModuleRegistry } from "../../../contracts/registries/ModuleRegistry.sol"; + +import { GrantNewAdminRole } from "../../../script/foundry/new-admin-role/GrantNewAdminRole.s.sol"; +import { JSONTxWriter } from "../../../script/foundry/utils/JSONTxWriter.s.sol"; + +import { stdJson } from "forge-std/StdJson.sol"; +import { BaseTest } from "test/foundry/utils/BaseTest.t.sol"; +// solhint-disable-next-line +import { console2 } from "forge-std/console2.sol"; + +contract GrantRolesToSafeTest is BaseTest { + event RoleLabel(uint64 indexed roleId, string label); + + // Maximum number of transactions in JSON files + uint256 public constant MAX_TXS_PER_JSON = 1000; + + string public constant OUTPUT_DIR = "./script/foundry/admin-actions/output-test/"; + + address securityCouncilSafeMultisig; + address governanceSafeMultisig; + uint256 delay; + + address groupNftAddr; + address licenseTokenAddr; + address ipGraphACLAddr; + address arbitrationPolicyUmaAddr; + address disputeModuleAddr; + address groupingModuleAddr; + address ipAssetRegistryAddr; + address licenseRegistryAddr; + address moduleRegistryAddr; + address royaltyModuleAddr; + address protocolPauseAdminAddr; + + bytes[] scheduleCalls; + bytes[] executeCalls; + bytes[] cancelCalls; + + function setUp() public override { + // Fork mainnet + uint256 forkId = vm.createFork("https://mainnet.storyrpc.io/"); + vm.selectFork(forkId); + + // relevant addresses + protocolAccessManager = AccessManager(0xFdece7b8a2f55ceC33b53fd28936B4B1e3153d53); + groupNftAddr = 0x4709798FeA84C84ae2475fF0c25344115eE1529f; + licenseTokenAddr = 0xFe3838BFb30B34170F00030B52eA4893d8aAC6bC; + ipGraphACLAddr = 0x1640A22a8A086747cD377b73954545e2Dfcc9Cad; + arbitrationPolicyUmaAddr = 0xfFD98c3877B8789124f02C7E8239A4b0Ef11E936; + disputeModuleAddr = 0x9b7A9c70AFF961C799110954fc06F3093aeb94C5; + groupingModuleAddr = 0x69D3a7aa9edb72Bc226E745A7cCdd50D947b69Ac; + ipAssetRegistryAddr = 0x77319B4031e6eF1250907aa00018B8B1c67a244b; + licenseRegistryAddr = 0x529a750E02d8E2f15649c13D69a465286a780e24; + moduleRegistryAddr = 0x022DBAAeA5D8fB31a0Ad793335e39Ced5D631fa5; + royaltyModuleAddr = 0xD2f60c40fEbccf6311f8B47c4f2Ec6b040400086; + protocolPauseAdminAddr = 0xdd661f55128A80437A0c0BDA6E13F214A3B2EB24; + + uint256 chainId = block.chainid; + if (chainId == 1514) { + delay = 5 days; + securityCouncilSafeMultisig = 0x25D2605b2C768082A14E79713114389d0eC297D8; + governanceSafeMultisig = 0xF07cA4b61022F0399C1511E7E668A57567f2138B; + } else if (chainId == 1315) { + delay = 10 minutes; + securityCouncilSafeMultisig = 0xC9a862Df1872402c4eAcbb8402F9BE628B52d270; + governanceSafeMultisig = 0x4B089bF9340DdB02a011471Eaa7d8D81C60CB524; + } + + GrantNewAdminRole deployScript = new GrantNewAdminRole(); + deployScript.run(true); + + // Get all transaction JSONs (schedule, cancel, execute) + ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) = _readNonRegularTransactionFiles("grant-new-admin-role"); + + assertEq(scheduleTxs.length, 15); + assertEq(executeTxs.length, 15); + assertEq(cancelTxs.length, 15); + + // Convert scheduleTxs to bytes array for multicall + scheduleCalls = new bytes[](scheduleTxs.length); + for (uint256 i = 0; i < scheduleTxs.length; i++) { + scheduleCalls[i] = scheduleTxs[i].data; + } + + // Convert executeTxs to bytes array for multicall + executeCalls = new bytes[](executeTxs.length); + for (uint256 i = 0; i < executeTxs.length; i++) { + executeCalls[i] = executeTxs[i].data; + } + + // Convert cancelTxs to bytes array for multicall + cancelCalls = new bytes[](cancelTxs.length); + for (uint256 i = 0; i < cancelTxs.length; i++) { + cancelCalls[i] = cancelTxs[i].data; + } + } + + function test_cancelTxs() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + + Multicall(address(protocolAccessManager)).multicall(cancelCalls); + + vm.expectRevert(); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + } + + function test_GroupNFT_setLicensingImageUrl() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(GroupNFT.setLicensingImageUrl.selector, "https://example.com"); + (bytes32 operationId, ) = protocolAccessManager.schedule(groupNftAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, groupNftAddr, data); + + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_LicenseToken_setLicensingImageUrl() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(LicenseToken.setLicensingImageUrl.selector, "https://example.com"); + (bytes32 operationId, ) = protocolAccessManager.schedule(licenseTokenAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, licenseTokenAddr, data); + + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_IPGraphACL_whitelistAddress() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(IPGraphACL.whitelistAddress.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(ipGraphACLAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, ipGraphACLAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_IPGraphACL_revokeWhitelistedAddress() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(IPGraphACL.revokeWhitelistedAddress.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(ipGraphACLAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, ipGraphACLAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_DisputeModule_whitelistDisputeTag() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(DisputeModule.whitelistDisputeTag.selector, "example", true); + (bytes32 operationId, ) = protocolAccessManager.schedule(disputeModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, disputeModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_DisputeModule_whitelistArbitrationPolicy() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(DisputeModule.whitelistArbitrationPolicy.selector, address(1), true); + (bytes32 operationId, ) = protocolAccessManager.schedule(disputeModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, disputeModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_DisputeModule_setArbitrationRelayer() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector( + DisputeModule.setArbitrationRelayer.selector, + address(1), + address(1) + ); + (bytes32 operationId, ) = protocolAccessManager.schedule(disputeModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, disputeModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_DisputeModule_setBaseArbitrationPolicy() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(DisputeModule.setBaseArbitrationPolicy.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(disputeModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, disputeModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_DisputeModule_setArbitrationPolicyCooldown() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(DisputeModule.setArbitrationPolicyCooldown.selector, uint256(100)); + (bytes32 operationId, ) = protocolAccessManager.schedule(disputeModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, disputeModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ArbitrationPolicyUMA_setOOV3() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(ArbitrationPolicyUMA.setOOV3.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(arbitrationPolicyUmaAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, arbitrationPolicyUmaAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ArbitrationPolicyUMA_setLiveness() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector( + ArbitrationPolicyUMA.setLiveness.selector, + uint64(100), + uint64(100), + uint32(100) + ); + (bytes32 operationId, ) = protocolAccessManager.schedule(arbitrationPolicyUmaAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, arbitrationPolicyUmaAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ArbitrationPolicyUMA_setMaxBond() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(ArbitrationPolicyUMA.setMaxBond.selector, address(1), uint256(100)); + (bytes32 operationId, ) = protocolAccessManager.schedule(arbitrationPolicyUmaAddr, data, 0); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, arbitrationPolicyUmaAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_GroupingModule_whitelistGroupRewardPool() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(GroupingModule.whitelistGroupRewardPool.selector, address(1), true); + (bytes32 operationId, ) = protocolAccessManager.schedule(groupingModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, groupingModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_RoyaltyModule_setTreasury() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(RoyaltyModule.setTreasury.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(royaltyModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, royaltyModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_RoyaltyModule_setRoyaltyFeePercent() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(RoyaltyModule.setRoyaltyFeePercent.selector, uint32(100)); + (bytes32 operationId, ) = protocolAccessManager.schedule(royaltyModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, royaltyModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_RoyaltyModule_setRoyaltyLimits() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(RoyaltyModule.setRoyaltyLimits.selector, uint256(100)); + (bytes32 operationId, ) = protocolAccessManager.schedule(royaltyModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, royaltyModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_RoyaltyModule_whitelistRoyaltyPolicy() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(RoyaltyModule.whitelistRoyaltyPolicy.selector, address(1), true); + (bytes32 operationId, ) = protocolAccessManager.schedule(royaltyModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, royaltyModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_RoyaltyModule_whitelistRoyaltyToken() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(RoyaltyModule.whitelistRoyaltyToken.selector, address(1), true); + (bytes32 operationId, ) = protocolAccessManager.schedule(royaltyModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, royaltyModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_VaultController_setIpRoyaltyVaultBeacon() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(VaultController.setIpRoyaltyVaultBeacon.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(royaltyModuleAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, royaltyModuleAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ProtocolPauseAdmin_addPausable() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(ProtocolPauseAdmin.addPausable.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(protocolPauseAdminAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, protocolPauseAdminAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ProtocolPauseAdmin_removePausable() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(ProtocolPauseAdmin.removePausable.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(protocolPauseAdminAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, protocolPauseAdminAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_IPAssetRegistry_setRegistrationFee() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector( + IPAssetRegistry.setRegistrationFee.selector, + address(1), + address(1), + uint96(100) + ); + (bytes32 operationId, ) = protocolAccessManager.schedule(ipAssetRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, ipAssetRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_LicenseRegistry_setDefaultLicenseTerms() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector( + LicenseRegistry.setDefaultLicenseTerms.selector, + address(1), + uint256(1) + ); + (bytes32 operationId, ) = protocolAccessManager.schedule(licenseRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, licenseRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_LicenseRegistry_registerLicenseTemplate() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(LicenseRegistry.registerLicenseTemplate.selector, address(1)); + (bytes32 operationId, ) = protocolAccessManager.schedule(licenseRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, licenseRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ModuleRegistry_registerModuleType() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector( + ModuleRegistry.registerModuleType.selector, + "TestModule", + bytes4(keccak256("testModule")) + ); + (bytes32 operationId, ) = protocolAccessManager.schedule(moduleRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, moduleRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ModuleRegistry_removeModuleType() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(ModuleRegistry.removeModuleType.selector, "TestModule"); + (bytes32 operationId, ) = protocolAccessManager.schedule(moduleRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, moduleRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ModuleRegistry_registerModule1() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector( + bytes4(keccak256("registerModule(string,address)")), + "TestModule", + address(1) + ); + (bytes32 operationId, ) = protocolAccessManager.schedule(moduleRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, moduleRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ModuleRegistry_registerModule2() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector( + bytes4(keccak256("registerModule(string,address,string)")), + "TestModule", + address(1), + "TestModule" + ); + (bytes32 operationId, ) = protocolAccessManager.schedule(moduleRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, moduleRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_ModuleRegistry_removeModule() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + bytes memory data = abi.encodeWithSelector(ModuleRegistry.removeModule.selector, "TestModule"); + (bytes32 operationId, ) = protocolAccessManager.schedule(moduleRegistryAddr, data, 0); + vm.stopPrank(); + + assertEq(protocolAccessManager.getSchedule(operationId), block.timestamp + delay); + + vm.startPrank(securityCouncilSafeMultisig); + protocolAccessManager.cancel(governanceSafeMultisig, moduleRegistryAddr, data); + assertEq(protocolAccessManager.getSchedule(operationId), 0); + } + + function test_labelRole() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + + vm.expectEmit(true, true, true, true); + emit RoleLabel(ProtocolAdmin.CANCELLABLE_ADMIN_ROLE, ProtocolAdmin.CANCELLABLE_ADMIN_ROLE_LABEL); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + } + + function test_setRoleGuardian() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + + assertEq(protocolAccessManager.getRoleGuardian(ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), 0); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + assertEq(protocolAccessManager.getRoleGuardian(ProtocolAdmin.CANCELLABLE_ADMIN_ROLE), 3); + } + + function test_grantRole() public { + vm.startPrank(governanceSafeMultisig); + Multicall(address(protocolAccessManager)).multicall(scheduleCalls); + skip(delay + 1); + + (bool isMemberBefore, uint32 executionDelayBefore) = protocolAccessManager.hasRole( + ProtocolAdmin.CANCELLABLE_ADMIN_ROLE, + governanceSafeMultisig + ); + + Multicall(address(protocolAccessManager)).multicall(executeCalls); + + (bool isMemberAfter, uint32 executionDelayAfter) = protocolAccessManager.hasRole( + ProtocolAdmin.CANCELLABLE_ADMIN_ROLE, + governanceSafeMultisig + ); + + assertEq(isMemberBefore, false); + assertEq(executionDelayBefore, 0); + assertEq(isMemberAfter, true); + assertEq(executionDelayAfter, delay); + } + + /** + * @notice Read transactions from schedule, cancel, and execute JSON files + * @param baseFilename The base filename without suffix (-schedule, -cancel, -execute) + * @return scheduleTxs Transaction struct from schedule file + * @return executeTxs Transaction struct from execute file + * @return cancelTxs Transaction struct from cancel file + */ + function _readNonRegularTransactionFiles( + string memory baseFilename + ) + internal + returns ( + JSONTxWriter.Transaction[] memory scheduleTxs, + JSONTxWriter.Transaction[] memory executeTxs, + JSONTxWriter.Transaction[] memory cancelTxs + ) + { + // Create paths for all three file types + string memory outputDir = OUTPUT_DIR; + string memory basePath = string.concat(outputDir, vm.toString(block.chainid), "/"); + string memory schedulePath = string.concat(basePath, baseFilename, "-schedule.json"); + string memory cancelPath = string.concat(basePath, baseFilename, "-cancel.json"); + string memory executePath = string.concat(basePath, baseFilename, "-execute.json"); + + // Read schedule transaction + assertTrue(vm.exists(schedulePath), "Schedule JSON file not found"); + string memory scheduleJson = vm.readFile(schedulePath); + JSONTxWriter.Transaction[] memory scheduleTxs = _parseTransactionsFromJson(scheduleJson); + + // Read cancel transaction + assertTrue(vm.exists(cancelPath), "Cancel JSON file not found"); + string memory cancelJson = vm.readFile(cancelPath); + JSONTxWriter.Transaction[] memory cancelTxs = _parseTransactionsFromJson(cancelJson); + + // Read execute transaction + assertTrue(vm.exists(executePath), "Execute JSON file not found"); + string memory executeJson = vm.readFile(executePath); + JSONTxWriter.Transaction[] memory executeTxs = _parseTransactionsFromJson(executeJson); + + return (scheduleTxs, executeTxs, cancelTxs); + } + + /** + * @notice Parse a JSON string into an array of Transaction structs + * @param json The JSON string to parse + * @return An array of Transaction structs + */ + function _parseTransactionsFromJson(string memory json) internal view returns (JSONTxWriter.Transaction[] memory) { + // Get the number of transactions in the JSON array + // Create an array to store the transactions + JSONTxWriter.Transaction[] memory readTxs = new JSONTxWriter.Transaction[](MAX_TXS_PER_JSON); + uint256 effectiveTxs = 0; + // Parse each transaction in the array + for (uint256 i = 0; i < MAX_TXS_PER_JSON; i++) { + try this._parseTransaction(json, i) returns (JSONTxWriter.Transaction memory transaction) { + readTxs[i] = transaction; + effectiveTxs++; + } catch { + // solhint-disable-next-line + console2.log("No more transactions in JSON"); + break; + } + } + + JSONTxWriter.Transaction[] memory transactions = new JSONTxWriter.Transaction[](effectiveTxs); + for (uint256 i = 0; i < effectiveTxs; i++) { + transactions[i] = readTxs[i]; + } + return transactions; + } + + function _parseTransaction( + string memory json, + uint256 index + ) external pure returns (JSONTxWriter.Transaction memory transaction) { + string memory indexPath = string.concat("[", vm.toString(index), "]"); + + address from = stdJson.readAddress(json, string.concat(indexPath, ".from")); + address to = stdJson.readAddress(json, string.concat(indexPath, ".to")); + uint256 value = stdJson.readUint(json, string.concat(indexPath, ".value")); + bytes memory data = stdJson.readBytes(json, string.concat(indexPath, ".data")); + uint8 operation = uint8(stdJson.readUint(json, string.concat(indexPath, ".operation"))); + string memory comment = stdJson.readString(json, string.concat(indexPath, ".comment")); + + // Create the transaction struct + return + JSONTxWriter.Transaction({ + from: from, + to: to, + value: value, + data: data, + operation: operation, + comment: comment + }); + } +}