From e3b1175a1ec382c108e0549c4c762bc33b858e10 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Sun, 14 Jan 2024 19:18:46 +0100 Subject: [PATCH 01/46] =?UTF-8?q?=F0=9F=9A=A7=20TimelockController=20main?= =?UTF-8?q?=20draft=20w/=20Access=20Control?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + src/governance/TimelockController.vy | 314 +++++++++++++++++++++++++++ 2 files changed, 317 insertions(+) create mode 100644 src/governance/TimelockController.vy diff --git a/.gitignore b/.gitignore index 67e04804..99eb7496 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,6 @@ venv # Python build files dist *.egg-info + +# Vyper build files +.build diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy new file mode 100644 index 00000000..68d14546 --- /dev/null +++ b/src/governance/TimelockController.vy @@ -0,0 +1,314 @@ +# pragma version ^0.3.10 + +# @dev We import and implement the `ERC165` interface, +# which is a built-in interface of the Vyper compiler. +from vyper.interfaces import ERC165 +implements: ERC165 + + +# @dev We import and implement the `IAccessControl` +# interface, which is written using standard Vyper +# syntax. +from ..auth.interfaces import IAccessControl +implements: IAccessControl + + +# @dev The default 32-byte admin role. +DEFAULT_ADMIN_ROLE: public(constant(bytes32)) = empty(bytes32) + + +# @dev An additional 32-byte access role. +# @notice Please adjust the naming of the variable +# according to your specific requirement, +# e.g. `MINTER_ROLE`. +ADDITIONAL_ROLE_1: public(constant(bytes32)) = keccak256("ADDITIONAL_ROLE_1") + + +# @dev An additional 32-byte access role. +# @notice Please adjust the naming of the variable +# according to your specific requirement, +# e.g. `PAUSER_ROLE`. Also, feel free to add more +# roles if necessary. In this case, it is important +# to extend the constructor accordingly. +ADDITIONAL_ROLE_2: public(constant(bytes32)) = keccak256("ADDITIONAL_ROLE_2") + + +# @dev Stores the ERC-165 interface identifier for each +# imported interface. The ERC-165 interface identifier +# is defined as the XOR of all function selectors in the +# interface. +_SUPPORTED_INTERFACES: constant(bytes4[2]) = [ + 0x01FFC9A7, # The ERC-165 identifier for ERC-165. + 0x7965DB0B, # The ERC-165 identifier for `IAccessControl`. +] + + +# @dev Returns `True` if `account` has been granted `role`. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. +hasRole: public(HashMap[bytes32, HashMap[address, bool]]) + + +# @dev Returns the admin role that controls `role`. +getRoleAdmin: public(HashMap[bytes32, bytes32]) + + +# @dev Emitted when `new_admin_role` is set as +# `role`'s admin role, replacing `previous_admin_role`. +# Note that `DEFAULT_ADMIN_ROLE` is the starting +# admin for all roles, despite `RoleAdminChanged` +# not being emitted signaling this. +event RoleAdminChanged: + role: indexed(bytes32) + previous_admin_role: indexed(bytes32) + new_admin_role: indexed(bytes32) + + +# @dev Emitted when `account` is granted `role`. +# Note that `sender` is the account (an admin +# role bearer) that originated the contract call. +event RoleGranted: + role: indexed(bytes32) + account: indexed(address) + sender: indexed(address) + + +# @dev Emitted when `account` is revoked `role`. +# Note that `sender` is the account that originated +# the contract call: +# - if using `revokeRole`, it is the admin role +# bearer, +# - if using `renounceRole`, it is the role bearer +# (i.e. `account`). +event RoleRevoked: + role: indexed(bytes32) + account: indexed(address) + sender: indexed(address) + +PROPOSER_ROLE: public(constant(bytes32)) = keccak256("PROPOSER_ROLE") + +EXECUTOR_ROLE: public(constant(bytes32)) = keccak256("EXECUTOR_ROLE") + +CANCELLER_ROLE: public(constant(bytes32)) = keccak256("CANCELLER_ROLE") + +_DONE_TIMESTAMP: constant(uint256) = 1 + +_timestamps: HashMap[bytes32, uint256] + +_minDelay: uint256 + +enum OperationState: + Unset + Waiting + Ready + Done + +event CallScheduled: + id: indexed(bytes32) + index: indexed(uint256) + target: address + value: uint256 + data: Bytes[1_024] + predecessor: bytes32 + delay: uint256 + +event CallExecuted: + id: indexed(bytes32) + index: indexed(uint256) + target: address + value: uint256 + data: Bytes[1_024] + +event CallSalt: + id: indexed(bytes32) + salt: bytes32 + +event Cancelled: + id: indexed(bytes32) + +event MinDelayChange: + oldDuration: uint256 + newDuration: uint256 + +# constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) { +# DynArray[address, 128] + +@external +@payable +def __init__(minDelay: uint256, proposers: DynArray[address, 128], executors: DynArray[address, 128], admin: address): + # Self administration + self._grant_role(DEFAULT_ADMIN_ROLE, self) + + # Optional admin + if (admin != empty(address)): + self._grant_role(DEFAULT_ADMIN_ROLE, admin) + + # Register proposers and cancellers + for proposer in proposers: + self._grant_role(PROPOSER_ROLE, proposer) + self._grant_role(CANCELLER_ROLE, proposer) + + # Register executors + for executor in executors: + self._grant_role(EXECUTOR_ROLE, executor) + + self._minDelay = minDelay + log MinDelayChange(0, minDelay) + + +@internal +def _onlyRoleOrOpenRole(role: bytes32): + if (not(self.hasRole[role][empty(address)])): + self._check_role(role, msg.sender) + +@external +@view +def supportsInterface(interface_id: bytes4) -> bool: + """ + @dev Returns `True` if this contract implements the + interface defined by `interface_id`. + @param interface_id The 4-byte interface identifier. + @return bool The verification whether the contract + implements the interface or not. + """ + return interface_id in _SUPPORTED_INTERFACES + +@external +@view +def isOperation(id: bytes32) -> bool: + return getOperationState(id) != OperationState.Unset + +@external +@view +def isOperationPending(id: bytes32) -> bool: + state: OperationState = getOperationState(id) + return state == OperationState.Waiting or state == OperationState.Ready + +@external +@view +def isOperationReady(id: bytes32) -> bool: + return getOperationState(id) == OperationState.Ready + +@external +@view +def isOperationDone(id: bytes32) -> bool: + return getOperationState(id) == OperationState.Done + +@external +@view +def getTimestamp(id: bytes32) -> uint256: + return self._timestamps[id] + +@external +def grantRole(role: bytes32, account: address): + """ + @dev Grants `role` to `account`. + @notice If `account` had not been already + granted `role`, emits a `RoleGranted` + event. Note that the caller must have + `role`'s admin role. + @param role The 32-byte role definition. + @param account The 20-byte address of the account. + """ + self._check_role(self.getRoleAdmin[role], msg.sender) + self._grant_role(role, account) + + +@external +def revokeRole(role: bytes32, account: address): + """ + @dev Revokes `role` from `account`. + @notice If `account` had been granted `role`, + emits a `RoleRevoked` event. Note that + the caller must have `role`'s admin role. + @param role The 32-byte role definition. + @param account The 20-byte address of the account. + """ + self._check_role(self.getRoleAdmin[role], msg.sender) + self._revoke_role(role, account) + + +@external +def renounceRole(role: bytes32, account: address): + """ + @dev Revokes `role` from the calling account. + @notice Roles are often managed via `grantRole` + and `revokeRole`. This function's purpose + is to provide a mechanism for accounts to + lose their privileges if they are compromised + (such as when a trusted device is misplaced). + If the calling account had been granted `role`, + emits a `RoleRevoked` event. Note that the + caller must be `account`. + @param role The 32-byte role definition. + @param account The 20-byte address of the account. + """ + assert account == msg.sender, "AccessControl: can only renounce roles for itself" + self._revoke_role(role, account) + + +@external +def set_role_admin(role: bytes32, admin_role: bytes32): + """ + @dev Sets `admin_role` as `role`'s admin role. + @notice Note that the caller must have `role`'s + admin role. + @param role The 32-byte role definition. + @param admin_role The new 32-byte admin role definition. + """ + self._check_role(self.getRoleAdmin[role], msg.sender) + self._set_role_admin(role, admin_role) + + +@internal +def _check_role(role: bytes32, account: address): + """ + @dev Reverts with a standard message if `account` + is missing `role`. + @param role The 32-byte role definition. + @param account The 20-byte address of the account. + """ + assert self.hasRole[role][account], "AccessControl: account is missing role" + + +@internal +def _set_role_admin(role: bytes32, admin_role: bytes32): + """ + @dev Sets `admin_role` as `role`'s admin role. + @notice This is an `internal` function without + access restriction. + @param role The 32-byte role definition. + @param admin_role The new 32-byte admin role definition. + """ + previous_admin_role: bytes32 = self.getRoleAdmin[role] + self.getRoleAdmin[role] = admin_role + log RoleAdminChanged(role, previous_admin_role, admin_role) + + +@internal +def _grant_role(role: bytes32, account: address): + """ + @dev Grants `role` to `account`. + @notice This is an `internal` function without + access restriction. + @param role The 32-byte role definition. + @param account The 20-byte address of the account. + """ + if (not(self.hasRole[role][account])): + self.hasRole[role][account] = True + log RoleGranted(role, account, msg.sender) + + +@internal +def _revoke_role(role: bytes32, account: address): + """ + @dev Revokes `role` from `account`. + @notice This is an `internal` function without + access restriction. + @param role The 32-byte role definition. + @param account The 20-byte address of the account. + """ + if (self.hasRole[role][account]): + self.hasRole[role][account] = False + log RoleRevoked(role, account, msg.sender) From ae3f1126ea40feaaaaad66e55a45d46b7dc250b0 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Sun, 14 Jan 2024 19:49:39 +0100 Subject: [PATCH 02/46] =?UTF-8?q?=E2=9C=A8=20Proposal=20execute,=20schedul?= =?UTF-8?q?e,=20and=20cancel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/governance/TimelockController.vy | 142 ++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 13 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 68d14546..503f731f 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -131,11 +131,7 @@ event MinDelayChange: oldDuration: uint256 newDuration: uint256 -# constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) { -# DynArray[address, 128] - @external -@payable def __init__(minDelay: uint256, proposers: DynArray[address, 128], executors: DynArray[address, 128], admin: address): # Self administration self._grant_role(DEFAULT_ADMIN_ROLE, self) @@ -156,6 +152,10 @@ def __init__(minDelay: uint256, proposers: DynArray[address, 128], executors: Dy self._minDelay = minDelay log MinDelayChange(0, minDelay) +@external +@payable +def __default__(): + pass @internal def _onlyRoleOrOpenRole(role: bytes32): @@ -174,32 +174,148 @@ def supportsInterface(interface_id: bytes4) -> bool: """ return interface_id in _SUPPORTED_INTERFACES -@external +# TODO: Most helper funtions below are originally public, but Vyper doesn't support that. wat do? + +@internal @view def isOperation(id: bytes32) -> bool: - return getOperationState(id) != OperationState.Unset + return self.getOperationState(id) != OperationState.Unset -@external +@internal @view def isOperationPending(id: bytes32) -> bool: - state: OperationState = getOperationState(id) + state: OperationState = self.getOperationState(id) return state == OperationState.Waiting or state == OperationState.Ready -@external +@internal @view def isOperationReady(id: bytes32) -> bool: - return getOperationState(id) == OperationState.Ready + return self.getOperationState(id) == OperationState.Ready -@external +@internal @view def isOperationDone(id: bytes32) -> bool: - return getOperationState(id) == OperationState.Done + return self.getOperationState(id) == OperationState.Done -@external +@internal @view def getTimestamp(id: bytes32) -> uint256: return self._timestamps[id] +@internal +@pure +def hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: + value: uint256 = x + return keccak256(_abi_encode(target, value, data, predecessor, salt)) + +@internal +@pure +def hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: + return keccak256(_abi_encode(targets, values, payloads, predecessor, salt)) + +@internal +@view +def getOperationState(id: bytes32) -> OperationState: + timestamp: uint256 = self.getTimestamp(id) + if (timestamp == 0): + return OperationState.Unset + elif (timestamp == _DONE_TIMESTAMP): + return OperationState.Done + elif (timestamp > block.timestamp): + return OperationState.Waiting + else: + return OperationState.Ready + +@external +def schedule(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32, delay: uint256): + self._check_role(PROPOSER_ROLE, msg.sender) + value: uint256 = x + id: bytes32 = self.hashOperation(target, value, data, predecessor, salt) + self._schedule(id, delay) + log CallScheduled(id, 0, target, value, data, predecessor, delay) + if (salt != empty(bytes32)): + log CallSalt(id, salt) + +@external +def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32, delay: uint256): + self._check_role(PROPOSER_ROLE, msg.sender) + assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" + id: bytes32 = self.hashOperationBatch(targets, values, payloads, predecessor, salt) + self._schedule(id, delay) + idx: uint256 = empty(uint256) + for target in targets: + log CallScheduled(id, idx, target, values[idx], payloads[idx], predecessor, delay) + # The following line cannot overflow because we have + # limited the dynamic array. + idx = unsafe_add(idx, 1) + if (salt != empty(bytes32)): + log CallSalt(id, salt) + +@internal +def _schedule(id: bytes32, delay: uint256): + assert not(self.isOperation(id)), "TimelockController: operation already scheduled" + assert delay >= self._minDelay, "TimelockController: insufficient delay" + self._timestamps[id] = block.timestamp + delay + +@external +def cancel(id: bytes32): + self._check_role(CANCELLER_ROLE, msg.sender) + assert self.isOperationPending(id), "TimelockController: operation cannot be cancelled" + self._timestamps[id] = 0 + log Cancelled(id) + +@external +def execute(target: address, x: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32): + self._onlyRoleOrOpenRole(EXECUTOR_ROLE) + value: uint256 = x + id: bytes32 = self.hashOperation(target, value, payload, predecessor, salt) + + self._beforeCall(id, predecessor) + self._execute(target, value, payload) + log CallExecuted(id, 0, target, value, payload) + self._afterCall(id) + +@external +def executeBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32): + self._onlyRoleOrOpenRole(EXECUTOR_ROLE) + assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" + id: bytes32 = self.hashOperationBatch(targets, values, payloads, predecessor, salt) + + self._beforeCall(id, predecessor) + idx: uint256 = empty(uint256) + for target in targets: + self._execute(target, values[idx], payloads[idx]) + log CallExecuted(id, idx, target, values[idx], payloads[idx]) + # The following line cannot overflow because we have + # limited the dynamic array. + idx = unsafe_add(idx, 1) + self._afterCall(id) + +@internal +def _execute(target: address, x: uint256, payload: Bytes[1_024]): + value: uint256 = x + return_data: Bytes[max_value(uint8)] = b"" + success: bool = empty(bool) + success, return_data = raw_call(target, payload, max_outsize=255, revert_on_failure=False) + assert success, "TimelockController: underlying transaction reverted" + +@internal +@view +def _beforeCall(id: bytes32, predecessor: bytes32): + assert self.isOperationReady(id), "TimelockController: operation is not ready" + assert predecessor == empty(bytes32) or self.isOperationDone(predecessor), "TimelockController: predecessor operation is not done" + +@internal +def _afterCall(id: bytes32): + assert self.isOperationReady(id), "TimelockController: operation is not ready" + self._timestamps[id] = _DONE_TIMESTAMP + +@external +def updateDelay(newDelay: uint256): + assert msg.sender == self, "TimelockController: unauthorized" + log MinDelayChange(self._minDelay, newDelay) + self._minDelay = newDelay + @external def grantRole(role: bytes32, account: address): """ From 81b19cf618bce66abf0a066c0ba2176b5d5ae354 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Sun, 14 Jan 2024 20:22:01 +0100 Subject: [PATCH 03/46] =?UTF-8?q?=F0=9F=8E=A8=20Forge=20formatter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/auth/AccessControl.t.sol | 175 +-- test/auth/Ownable.t.sol | 22 +- test/auth/Ownable2Step.t.sol | 42 +- test/auth/interfaces/IOwnable.sol | 5 +- test/auth/interfaces/IOwnable2Step.sol | 10 +- test/extensions/ERC2981.t.sol | 260 +--- test/extensions/ERC4626.t.sol | 1377 +++-------------- .../interfaces/IERC2981Extended.sol | 16 +- .../interfaces/IERC4626Extended.sol | 7 +- test/tokens/ERC1155.t.sol | 1215 +++------------ test/tokens/ERC20.t.sol | 326 +--- test/tokens/ERC721.t.sol | 745 ++------- test/tokens/interfaces/IERC1155Extended.sol | 28 +- test/tokens/interfaces/IERC20Extended.sol | 5 +- test/tokens/interfaces/IERC4494.sol | 9 +- test/tokens/interfaces/IERC721Extended.sol | 13 +- test/tokens/mocks/ERC1155ReceiverMock.sol | 34 +- test/tokens/mocks/ERC721ReceiverMock.sol | 12 +- test/utils/Base64.t.sol | 36 +- test/utils/BatchDistributor.t.sol | 293 +--- test/utils/Create2Address.t.sol | 102 +- test/utils/CreateAddress.t.sol | 716 ++------- test/utils/ECDSA.t.sol | 126 +- test/utils/EIP712DomainSeparator.t.sol | 103 +- test/utils/Math.t.sol | 101 +- test/utils/MerkleProofVerification.t.sol | 318 +--- test/utils/Multicall.t.sol | 291 +--- test/utils/SignatureChecker.t.sol | 264 +--- test/utils/interfaces/IBase64.sol | 10 +- test/utils/interfaces/ICreate2Address.sol | 11 +- test/utils/interfaces/ICreateAddress.sol | 9 +- test/utils/interfaces/IECDSA.sol | 26 +- .../interfaces/IEIP712DomainSeparator.sol | 4 +- test/utils/interfaces/IMath.sol | 12 +- .../interfaces/IMerkleProofVerification.sol | 6 +- test/utils/interfaces/IMulticall.sol | 16 +- test/utils/interfaces/ISignatureChecker.sol | 18 +- test/utils/mocks/Create2Impl.sol | 15 +- test/utils/mocks/ERC1271MaliciousMock.sol | 10 +- test/utils/mocks/ERC1271WalletMock.sol | 10 +- test/utils/mocks/ERC20Mock.sol | 10 +- test/utils/mocks/MockCallee.sol | 6 +- 42 files changed, 1280 insertions(+), 5534 deletions(-) diff --git a/test/auth/AccessControl.t.sol b/test/auth/AccessControl.t.sol index 43eae8ab..937d8b85 100644 --- a/test/auth/AccessControl.t.sol +++ b/test/auth/AccessControl.t.sol @@ -22,9 +22,7 @@ contract AccessControlTest is Test { address private deployer = address(vyperDeployer); function setUp() public { - accessControl = IAccessControlExtended( - vyperDeployer.deployContract("src/auth/", "AccessControl") - ); + accessControl = IAccessControlExtended(vyperDeployer.deployContract("src/auth/", "AccessControl")); } function testInitialSetup() public { @@ -34,18 +32,9 @@ contract AccessControlTest is Test { assertTrue(accessControl.hasRole(DEFAULT_ADMIN_ROLE, deployer)); assertTrue(accessControl.hasRole(ADDITIONAL_ROLE_1, deployer)); assertTrue(accessControl.hasRole(ADDITIONAL_ROLE_2, deployer)); - assertEq( - accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), - DEFAULT_ADMIN_ROLE - ); - assertEq( - accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), - DEFAULT_ADMIN_ROLE - ); - assertEq( - accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), - DEFAULT_ADMIN_ROLE - ); + assertEq(accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), DEFAULT_ADMIN_ROLE); + assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), DEFAULT_ADMIN_ROLE); + assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), DEFAULT_ADMIN_ROLE); vm.expectEmit(true, true, true, false); emit IAccessControl.RoleGranted(DEFAULT_ADMIN_ROLE, deployer, deployer); @@ -53,59 +42,28 @@ contract AccessControlTest is Test { emit IAccessControl.RoleGranted(ADDITIONAL_ROLE_1, deployer, deployer); vm.expectEmit(true, true, true, false); emit IAccessControl.RoleGranted(ADDITIONAL_ROLE_2, deployer, deployer); - accessControlInitialEvent = IAccessControlExtended( - vyperDeployer.deployContract("src/auth/", "AccessControl") - ); - assertEq( - accessControlInitialEvent.DEFAULT_ADMIN_ROLE(), - DEFAULT_ADMIN_ROLE - ); - assertEq( - accessControlInitialEvent.ADDITIONAL_ROLE_1(), - ADDITIONAL_ROLE_1 - ); - assertEq( - accessControlInitialEvent.ADDITIONAL_ROLE_2(), - ADDITIONAL_ROLE_2 - ); - assertTrue( - accessControlInitialEvent.hasRole(DEFAULT_ADMIN_ROLE, deployer) - ); - assertTrue( - accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_1, deployer) - ); - assertTrue( - accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_2, deployer) - ); - assertEq( - accessControlInitialEvent.getRoleAdmin(DEFAULT_ADMIN_ROLE), - DEFAULT_ADMIN_ROLE - ); - assertEq( - accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_1), - DEFAULT_ADMIN_ROLE - ); - assertEq( - accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_2), - DEFAULT_ADMIN_ROLE - ); + accessControlInitialEvent = IAccessControlExtended(vyperDeployer.deployContract("src/auth/", "AccessControl")); + assertEq(accessControlInitialEvent.DEFAULT_ADMIN_ROLE(), DEFAULT_ADMIN_ROLE); + assertEq(accessControlInitialEvent.ADDITIONAL_ROLE_1(), ADDITIONAL_ROLE_1); + assertEq(accessControlInitialEvent.ADDITIONAL_ROLE_2(), ADDITIONAL_ROLE_2); + assertTrue(accessControlInitialEvent.hasRole(DEFAULT_ADMIN_ROLE, deployer)); + assertTrue(accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_1, deployer)); + assertTrue(accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_2, deployer)); + assertEq(accessControlInitialEvent.getRoleAdmin(DEFAULT_ADMIN_ROLE), DEFAULT_ADMIN_ROLE); + assertEq(accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_1), DEFAULT_ADMIN_ROLE); + assertEq(accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_2), DEFAULT_ADMIN_ROLE); } function testSupportsInterfaceSuccess() public { assertTrue(accessControl.supportsInterface(type(IERC165).interfaceId)); - assertTrue( - accessControl.supportsInterface(type(IAccessControl).interfaceId) - ); + assertTrue(accessControl.supportsInterface(type(IAccessControl).interfaceId)); } function testSupportsInterfaceSuccessGasCost() public { uint256 startGas = gasleft(); accessControl.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && - accessControl.supportsInterface(type(IERC165).interfaceId) - ); + assertTrue(gasUsed <= 30_000 && accessControl.supportsInterface(type(IERC165).interfaceId)); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -116,9 +74,7 @@ contract AccessControlTest is Test { uint256 startGas = gasleft(); accessControl.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && !accessControl.supportsInterface(0x0011bbff) - ); + assertTrue(gasUsed <= 30_000 && !accessControl.supportsInterface(0x0011bbff)); } function testGrantRoleSuccess() public { @@ -291,9 +247,7 @@ contract AccessControlTest is Test { } function testRenounceRoleNonMsgSender() public { - vm.expectRevert( - bytes("AccessControl: can only renounce roles for itself") - ); + vm.expectRevert(bytes("AccessControl: can only renounce roles for itself")); accessControl.renounceRole(ADDITIONAL_ROLE_1, makeAddr("account")); } @@ -304,11 +258,7 @@ contract AccessControlTest is Test { bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged( - ADDITIONAL_ROLE_1, - DEFAULT_ADMIN_ROLE, - otherAdminRole - ); + emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -338,11 +288,7 @@ contract AccessControlTest is Test { bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged( - ADDITIONAL_ROLE_1, - DEFAULT_ADMIN_ROLE, - otherAdminRole - ); + emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -364,11 +310,7 @@ contract AccessControlTest is Test { accessControl.grantRole(ADDITIONAL_ROLE_1, account); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged( - ADDITIONAL_ROLE_1, - DEFAULT_ADMIN_ROLE, - otherAdminRole - ); + emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -420,10 +362,7 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzGrantRoleNonAdmin( - address nonAdmin, - address account - ) public { + function testFuzzGrantRoleNonAdmin(address nonAdmin, address account) public { vm.assume(nonAdmin != deployer); vm.prank(nonAdmin); vm.expectRevert(bytes("AccessControl: account is missing role")); @@ -472,10 +411,7 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzRevokeRoleNonAdmin( - address nonAdmin, - address account - ) public { + function testFuzzRevokeRoleNonAdmin(address nonAdmin, address account) public { vm.assume(nonAdmin != deployer); vm.prank(nonAdmin); vm.expectRevert(bytes("AccessControl: account is missing role")); @@ -534,26 +470,17 @@ contract AccessControlTest is Test { function testFuzzRenounceRoleNonMsgSender(address account) public { vm.assume(address(this) != account); - vm.expectRevert( - bytes("AccessControl: can only renounce roles for itself") - ); + vm.expectRevert(bytes("AccessControl: can only renounce roles for itself")); accessControl.renounceRole(ADDITIONAL_ROLE_1, account); } - function testFuzzSetRoleAdminSuccess( - address otherAdmin, - address account - ) public { + function testFuzzSetRoleAdminSuccess(address otherAdmin, address account) public { vm.assume(otherAdmin != deployer && account != deployer); address admin = deployer; bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged( - ADDITIONAL_ROLE_1, - DEFAULT_ADMIN_ROLE, - otherAdminRole - ); + emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -576,20 +503,13 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzSetRoleAdminPreviousAdminCallsGrantRole( - address otherAdmin, - address account - ) public { + function testFuzzSetRoleAdminPreviousAdminCallsGrantRole(address otherAdmin, address account) public { vm.assume(otherAdmin != deployer); address admin = deployer; bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged( - ADDITIONAL_ROLE_1, - DEFAULT_ADMIN_ROLE, - otherAdminRole - ); + emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -602,10 +522,7 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzSetRoleAdminPreviousAdminCallsRevokeRole( - address otherAdmin, - address account - ) public { + function testFuzzSetRoleAdminPreviousAdminCallsRevokeRole(address otherAdmin, address account) public { vm.assume(otherAdmin != deployer); address admin = deployer; bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); @@ -613,11 +530,7 @@ contract AccessControlTest is Test { accessControl.grantRole(ADDITIONAL_ROLE_1, account); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged( - ADDITIONAL_ROLE_1, - DEFAULT_ADMIN_ROLE, - otherAdminRole - ); + emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -644,16 +557,9 @@ contract AccessControlInvariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - accessControl = IAccessControlExtended( - vyperDeployer.deployContract("src/auth/", "AccessControl") - ); - accessControlHandler = new AccessControlHandler( - accessControl, - deployer, - DEFAULT_ADMIN_ROLE, - ADDITIONAL_ROLE_1, - ADDITIONAL_ROLE_2 - ); + accessControl = IAccessControlExtended(vyperDeployer.deployContract("src/auth/", "AccessControl")); + accessControlHandler = + new AccessControlHandler(accessControl, deployer, DEFAULT_ADMIN_ROLE, ADDITIONAL_ROLE_1, ADDITIONAL_ROLE_2); targetContract(address(accessControlHandler)); } @@ -673,18 +579,9 @@ contract AccessControlInvariants is Test { } function invariantGetRoleAdmin() public { - assertEq( - accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), - accessControlHandler.getRoleAdmin(DEFAULT_ADMIN_ROLE) - ); - assertEq( - accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), - accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_1) - ); - assertEq( - accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), - accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_2) - ); + assertEq(accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), accessControlHandler.getRoleAdmin(DEFAULT_ADMIN_ROLE)); + assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_1)); + assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_2)); } } diff --git a/test/auth/Ownable.t.sol b/test/auth/Ownable.t.sol index 6e74b347..5249157b 100644 --- a/test/auth/Ownable.t.sol +++ b/test/auth/Ownable.t.sol @@ -16,9 +16,7 @@ contract OwnableTest is Test { address private zeroAddress = address(0); function setUp() public { - ownable = IOwnable( - vyperDeployer.deployContract("src/auth/", "Ownable") - ); + ownable = IOwnable(vyperDeployer.deployContract("src/auth/", "Ownable")); } function testInitialSetup() public { @@ -26,9 +24,7 @@ contract OwnableTest is Test { vm.expectEmit(true, true, false, false); emit IOwnable.OwnershipTransferred(zeroAddress, deployer); - ownableInitialEvent = IOwnable( - vyperDeployer.deployContract("src/auth/", "Ownable") - ); + ownableInitialEvent = IOwnable(vyperDeployer.deployContract("src/auth/", "Ownable")); assertEq(ownableInitialEvent.owner(), deployer); } @@ -74,10 +70,7 @@ contract OwnableTest is Test { ownable.renounce_ownership(); } - function testFuzzTransferOwnershipSuccess( - address newOwner1, - address newOwner2 - ) public { + function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -95,10 +88,7 @@ contract OwnableTest is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner( - address nonOwner, - address newOwner - ) public { + function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -141,9 +131,7 @@ contract OwnableInvariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - ownable = IOwnable( - vyperDeployer.deployContract("src/auth/", "Ownable") - ); + ownable = IOwnable(vyperDeployer.deployContract("src/auth/", "Ownable")); ownerHandler = new OwnerHandler(ownable, deployer); targetContract(address(ownerHandler)); } diff --git a/test/auth/Ownable2Step.t.sol b/test/auth/Ownable2Step.t.sol index e26d0ed7..77a4ef4a 100644 --- a/test/auth/Ownable2Step.t.sol +++ b/test/auth/Ownable2Step.t.sol @@ -16,9 +16,7 @@ contract Ownable2StepTest is Test { address private zeroAddress = address(0); function setUp() public { - ownable2Step = IOwnable2Step( - vyperDeployer.deployContract("src/auth/", "Ownable2Step") - ); + ownable2Step = IOwnable2Step(vyperDeployer.deployContract("src/auth/", "Ownable2Step")); } function testInitialSetup() public { @@ -27,9 +25,7 @@ contract Ownable2StepTest is Test { vm.expectEmit(true, true, false, false); emit IOwnable2Step.OwnershipTransferred(zeroAddress, deployer); - ownable2StepInitialEvent = IOwnable2Step( - vyperDeployer.deployContract("src/auth/", "Ownable2Step") - ); + ownable2StepInitialEvent = IOwnable2Step(vyperDeployer.deployContract("src/auth/", "Ownable2Step")); assertEq(ownable2StepInitialEvent.owner(), deployer); assertEq(ownable2StepInitialEvent.pending_owner(), zeroAddress); } @@ -130,10 +126,7 @@ contract Ownable2StepTest is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipSuccess( - address newOwner1, - address newOwner2 - ) public { + function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -152,20 +145,14 @@ contract Ownable2StepTest is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner( - address nonOwner, - address newOwner - ) public { + function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable2Step: caller is not the owner")); ownable2Step.transfer_ownership(newOwner); } - function testFuzzAcceptOwnershipSuccess( - address newOwner1, - address newOwner2 - ) public { + function testFuzzAcceptOwnershipSuccess(address newOwner1, address newOwner2) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -249,9 +236,7 @@ contract Ownable2StepTest is Test { ownable2Step.renounce_ownership(); } - function testFuzzPendingOwnerResetAfterRenounceOwnership( - address newOwner - ) public { + function testFuzzPendingOwnerResetAfterRenounceOwnership(address newOwner) public { vm.assume(newOwner != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -284,14 +269,8 @@ contract Ownable2StepInvariants is Test { address private zeroAddress = address(0); function setUp() public { - ownable2Step = IOwnable2Step( - vyperDeployer.deployContract("src/auth/", "Ownable2Step") - ); - owner2StepHandler = new Owner2StepHandler( - ownable2Step, - deployer, - zeroAddress - ); + ownable2Step = IOwnable2Step(vyperDeployer.deployContract("src/auth/", "Ownable2Step")); + owner2StepHandler = new Owner2StepHandler(ownable2Step, deployer, zeroAddress); targetContract(address(owner2StepHandler)); } @@ -300,10 +279,7 @@ contract Ownable2StepInvariants is Test { } function invariantPendingOwner() public { - assertEq( - ownable2Step.pending_owner(), - owner2StepHandler.pending_owner() - ); + assertEq(ownable2Step.pending_owner(), owner2StepHandler.pending_owner()); } } diff --git a/test/auth/interfaces/IOwnable.sol b/test/auth/interfaces/IOwnable.sol index 629dbcb2..8f1b015a 100644 --- a/test/auth/interfaces/IOwnable.sol +++ b/test/auth/interfaces/IOwnable.sol @@ -2,10 +2,7 @@ pragma solidity ^0.8.23; interface IOwnable { - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function owner() external view returns (address); diff --git a/test/auth/interfaces/IOwnable2Step.sol b/test/auth/interfaces/IOwnable2Step.sol index 18c98f85..7054c607 100644 --- a/test/auth/interfaces/IOwnable2Step.sol +++ b/test/auth/interfaces/IOwnable2Step.sol @@ -2,15 +2,9 @@ pragma solidity ^0.8.23; interface IOwnable2Step { - event OwnershipTransferStarted( - address indexed previousOwner, - address indexed newOwner - ); + event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function owner() external view returns (address); diff --git a/test/extensions/ERC2981.t.sol b/test/extensions/ERC2981.t.sol index 9327b1bf..e302026c 100644 --- a/test/extensions/ERC2981.t.sol +++ b/test/extensions/ERC2981.t.sol @@ -21,53 +21,37 @@ contract ERC2981Test is Test { address private zeroAddress = address(0); function setUp() public { - ERC2981Extended = IERC2981Extended( - vyperDeployer.deployContract("src/extensions/", "ERC2981") - ); + ERC2981Extended = IERC2981Extended(vyperDeployer.deployContract("src/extensions/", "ERC2981")); } function testInitialSetup() public { uint256 tokenId = 1; uint256 salePrice = 1_000; - (address receiver, uint256 royaltyAmount) = ERC2981Extended.royaltyInfo( - tokenId, - salePrice - ); + (address receiver, uint256 royaltyAmount) = ERC2981Extended.royaltyInfo(tokenId, salePrice); assertEq(ERC2981Extended.owner(), deployer); assertEq(receiver, zeroAddress); assertEq(royaltyAmount, 0); vm.expectEmit(true, true, false, false); emit IERC2981Extended.OwnershipTransferred(zeroAddress, deployer); - ERC2981ExtendedInitialEvent = IERC2981Extended( - vyperDeployer.deployContract("src/extensions/", "ERC2981") - ); - ( - address receiverInitialSetup, - uint256 royaltyAmountInitialSetup - ) = ERC2981ExtendedInitialEvent.royaltyInfo(tokenId, salePrice); + ERC2981ExtendedInitialEvent = IERC2981Extended(vyperDeployer.deployContract("src/extensions/", "ERC2981")); + (address receiverInitialSetup, uint256 royaltyAmountInitialSetup) = + ERC2981ExtendedInitialEvent.royaltyInfo(tokenId, salePrice); assertEq(ERC2981ExtendedInitialEvent.owner(), deployer); assertEq(receiverInitialSetup, zeroAddress); assertEq(royaltyAmountInitialSetup, 0); } function testSupportsInterfaceSuccess() public { - assertTrue( - ERC2981Extended.supportsInterface(type(IERC165).interfaceId) - ); - assertTrue( - ERC2981Extended.supportsInterface(type(IERC2981).interfaceId) - ); + assertTrue(ERC2981Extended.supportsInterface(type(IERC165).interfaceId)); + assertTrue(ERC2981Extended.supportsInterface(type(IERC2981).interfaceId)); } function testSupportsInterfaceSuccessGasCost() public { uint256 startGas = gasleft(); ERC2981Extended.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && - ERC2981Extended.supportsInterface(type(IERC165).interfaceId) - ); + assertTrue(gasUsed <= 30_000 && ERC2981Extended.supportsInterface(type(IERC165).interfaceId)); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -78,9 +62,7 @@ contract ERC2981Test is Test { uint256 startGas = gasleft(); ERC2981Extended.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && !ERC2981Extended.supportsInterface(0x0011bbff) - ); + assertTrue(gasUsed <= 30_000 && !ERC2981Extended.supportsInterface(0x0011bbff)); } function testRoyaltyInfoDefaultRoyalty() public { @@ -93,10 +75,8 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -118,10 +98,8 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver1, receiverAddr1); @@ -130,10 +108,8 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.set_default_royalty(receiver2, royaltyFraction * 2); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -153,10 +129,8 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -165,10 +139,8 @@ contract ERC2981Test is Test { assertEq(royalty, royaltyAmount2); ERC2981Extended.delete_default_royalty(); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiverAddr3, zeroAddress); @@ -190,15 +162,9 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty( - tokenId1, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertTrue(royaltyAmount1 != royaltyAmount2); assertEq(receiver2, receiverAddr1); @@ -220,15 +186,9 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty( - tokenId1, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertTrue(royaltyAmount1 != royaltyAmount2); assertEq(receiver2, receiverAddr1); @@ -236,15 +196,9 @@ contract ERC2981Test is Test { assertEq(receiver1, receiverAddr2); assertEq(royalty1, royaltyAmount2); - ERC2981Extended.set_token_royalty( - tokenId2, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId2, receiver2, royaltyFraction * 2); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -266,15 +220,9 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty( - tokenId1, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertTrue(royaltyAmount1 != royaltyAmount2); assertEq(receiver2, receiverAddr1); @@ -283,8 +231,7 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.reset_token_royalty(tokenId1); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); assertEq(receiverAddr3, receiverAddr2); assertEq(royaltyAmount3, royaltyAmount2); assertEq(receiver1, receiverAddr2); @@ -410,10 +357,8 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -432,10 +377,7 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && - receiver2 != zeroAddress && - receiver1 != receiver2 && - tokenId1 != tokenId2 + receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -443,10 +385,8 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver1, receiverAddr1); @@ -455,10 +395,8 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.set_default_royalty(receiver2, royaltyFraction * 2); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -481,10 +419,8 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -493,10 +429,8 @@ contract ERC2981Test is Test { assertEq(royalty, royaltyAmount2); ERC2981Extended.delete_default_royalty(); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiverAddr3, zeroAddress); @@ -515,10 +449,7 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && - receiver2 != zeroAddress && - receiver1 != receiver2 && - tokenId1 != tokenId2 + receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -526,15 +457,9 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty( - tokenId1, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertEq(receiver2, receiverAddr1); assertEq(royalty2, royaltyAmount1); @@ -552,10 +477,7 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && - receiver2 != zeroAddress && - receiver1 != receiver2 && - tokenId1 != tokenId2 + receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -563,30 +485,18 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty( - tokenId1, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertEq(receiver2, receiverAddr1); assertEq(royalty2, royaltyAmount1); assertEq(receiver1, receiverAddr2); assertEq(royalty1, royaltyAmount2); - ERC2981Extended.set_token_royalty( - tokenId2, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId2, receiver2, royaltyFraction * 2); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -605,10 +515,7 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && - receiver2 != zeroAddress && - receiver1 != receiver2 && - tokenId1 != tokenId2 + receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -616,15 +523,9 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty( - tokenId1, - receiver2, - royaltyFraction * 2 - ); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended - .royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertEq(receiver2, receiverAddr1); assertEq(royalty2, royaltyAmount1); @@ -632,8 +533,7 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.reset_token_royalty(tokenId1); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended - .royaltyInfo(tokenId1, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); assertEq(receiverAddr3, receiverAddr2); assertEq(royaltyAmount3, royaltyAmount2); assertEq(receiver1, receiverAddr2); @@ -643,12 +543,8 @@ contract ERC2981Test is Test { vm.stopPrank(); } - function testFuzzSetDefaultRoyaltyTooHighFeeNumerator( - uint96 feeNumerator - ) public { - feeNumerator = uint96( - bound(uint256(feeNumerator), 10_001, type(uint96).max) - ); + function testFuzzSetDefaultRoyaltyTooHighFeeNumerator(uint96 feeNumerator) public { + feeNumerator = uint96(bound(uint256(feeNumerator), 10_001, type(uint96).max)); address owner = deployer; vm.startPrank(owner); vm.expectRevert("ERC2981: royalty fee will exceed sale_price"); @@ -668,20 +564,12 @@ contract ERC2981Test is Test { ERC2981Extended.delete_default_royalty(); } - function testFuzzSetTokenRoyaltyTooHighFeeNumerator( - uint96 feeNumerator - ) public { - feeNumerator = uint96( - bound(uint256(feeNumerator), 10_001, type(uint96).max) - ); + function testFuzzSetTokenRoyaltyTooHighFeeNumerator(uint96 feeNumerator) public { + feeNumerator = uint96(bound(uint256(feeNumerator), 10_001, type(uint96).max)); address owner = deployer; vm.startPrank(owner); vm.expectRevert("ERC2981: royalty fee will exceed sale_price"); - ERC2981Extended.set_token_royalty( - 1, - makeAddr("receiver"), - feeNumerator - ); + ERC2981Extended.set_token_royalty(1, makeAddr("receiver"), feeNumerator); vm.stopPrank(); } @@ -706,10 +594,7 @@ contract ERC2981Test is Test { ERC2981Extended.reset_token_royalty(1); } - function testFuzzTransferOwnershipSuccess( - address newOwner1, - address newOwner2 - ) public { + function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -727,10 +612,7 @@ contract ERC2981Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner( - address nonOwner, - address newOwner - ) public { + function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -774,9 +656,7 @@ contract ERC2981Invariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - ERC2981Extended = IERC2981Extended( - vyperDeployer.deployContract("src/extensions/", "ERC2981") - ); + ERC2981Extended = IERC2981Extended(vyperDeployer.deployContract("src/extensions/", "ERC2981")); erc2981Handler = new ERC2981Handler(ERC2981Extended, deployer); targetContract(address(erc2981Handler)); targetSender(deployer); @@ -807,11 +687,7 @@ contract ERC2981Handler { erc2981.delete_default_royalty(); } - function set_token_royalty( - uint256 tokenId, - address receiver, - uint96 feeNumerator - ) public { + function set_token_royalty(uint256 tokenId, address receiver, uint96 feeNumerator) public { erc2981.set_token_royalty(tokenId, receiver, feeNumerator); } diff --git a/test/extensions/ERC4626.t.sol b/test/extensions/ERC4626.t.sol index 7c526658..dea6817e 100644 --- a/test/extensions/ERC4626.t.sol +++ b/test/extensions/ERC4626.t.sol @@ -24,26 +24,13 @@ contract ERC4626VaultTest is ERC4626Test { uint8 private constant _DECIMALS_OFFSET = 0; uint256 private constant _INITIAL_SUPPLY_UNDERLYING = type(uint8).max; bytes32 private constant _TYPE_HASH = - keccak256( - bytes( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ) - ); + keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256( - bytes( - "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" - ) - ); + keccak256(bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")); VyperDeployer private vyperDeployer = new VyperDeployer(); ERC20Mock private underlying = - new ERC20Mock( - _NAME_UNDERLYING, - _SYMBOL_UNDERLYING, - makeAddr("initialAccount"), - _INITIAL_SUPPLY_UNDERLYING - ); + new ERC20Mock(_NAME_UNDERLYING, _SYMBOL_UNDERLYING, makeAddr("initialAccount"), _INITIAL_SUPPLY_UNDERLYING); /* solhint-disable var-name-mixedcase */ IERC4626Extended private ERC4626ExtendedDecimalsOffset0; @@ -66,24 +53,11 @@ contract ERC4626VaultTest is ERC4626Test { address private ERC4626ExtendedDecimalsOffset18Addr; function setUp() public override { - bytes memory argsDecimalsOffset0 = abi.encode( - _NAME, - _SYMBOL, - underlying, - _DECIMALS_OFFSET, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC4626ExtendedDecimalsOffset0 = IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffset0 - ) - ); - ERC4626ExtendedDecimalsOffset0Addr = address( - ERC4626ExtendedDecimalsOffset0 - ); + bytes memory argsDecimalsOffset0 = + abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET, _NAME_EIP712, _VERSION_EIP712); + ERC4626ExtendedDecimalsOffset0 = + IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset0)); + ERC4626ExtendedDecimalsOffset0Addr = address(ERC4626ExtendedDecimalsOffset0); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( _TYPE_HASH, @@ -94,62 +68,23 @@ contract ERC4626VaultTest is ERC4626Test { ) ); - bytes memory argsDecimalsOffset6 = abi.encode( - _NAME, - _SYMBOL, - underlying, - _DECIMALS_OFFSET + 6, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC4626ExtendedDecimalsOffset6 = IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffset6 - ) - ); - ERC4626ExtendedDecimalsOffset6Addr = address( - ERC4626ExtendedDecimalsOffset6 - ); + bytes memory argsDecimalsOffset6 = + abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET + 6, _NAME_EIP712, _VERSION_EIP712); + ERC4626ExtendedDecimalsOffset6 = + IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset6)); + ERC4626ExtendedDecimalsOffset6Addr = address(ERC4626ExtendedDecimalsOffset6); - bytes memory argsDecimalsOffset12 = abi.encode( - _NAME, - _SYMBOL, - underlying, - _DECIMALS_OFFSET + 12, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC4626ExtendedDecimalsOffset12 = IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffset12 - ) - ); - ERC4626ExtendedDecimalsOffset12Addr = address( - ERC4626ExtendedDecimalsOffset12 - ); + bytes memory argsDecimalsOffset12 = + abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET + 12, _NAME_EIP712, _VERSION_EIP712); + ERC4626ExtendedDecimalsOffset12 = + IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset12)); + ERC4626ExtendedDecimalsOffset12Addr = address(ERC4626ExtendedDecimalsOffset12); - bytes memory argsDecimalsOffset18 = abi.encode( - _NAME, - _SYMBOL, - underlying, - _DECIMALS_OFFSET + 18, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC4626ExtendedDecimalsOffset18 = IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffset18 - ) - ); - ERC4626ExtendedDecimalsOffset18Addr = address( - ERC4626ExtendedDecimalsOffset18 - ); + bytes memory argsDecimalsOffset18 = + abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET + 18, _NAME_EIP712, _VERSION_EIP712); + ERC4626ExtendedDecimalsOffset18 = + IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset18)); + ERC4626ExtendedDecimalsOffset18Addr = address(ERC4626ExtendedDecimalsOffset18); /** * @dev ERC-4626 property tests (https://github.com/a16z/erc4626-tests) setup. @@ -185,49 +120,24 @@ contract ERC4626VaultTest is ERC4626Test { /** * @dev Check the case where the asset has not yet been created. */ - bytes memory argsDecimalsOffsetEOA = abi.encode( - _NAME, - _SYMBOL, - makeAddr("someAccount"), - _DECIMALS_OFFSET + 3, - _NAME_EIP712, - _VERSION_EIP712 - ); + bytes memory argsDecimalsOffsetEOA = + abi.encode(_NAME, _SYMBOL, makeAddr("someAccount"), _DECIMALS_OFFSET + 3, _NAME_EIP712, _VERSION_EIP712); // solhint-disable-next-line var-name-mixedcase - IERC4626Extended ERC4626ExtendedDecimalsOffsetEOA = IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffsetEOA - ) - ); + IERC4626Extended ERC4626ExtendedDecimalsOffsetEOA = + IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetEOA)); assertEq(ERC4626ExtendedDecimalsOffsetEOA.name(), _NAME); assertEq(ERC4626ExtendedDecimalsOffsetEOA.symbol(), _SYMBOL); assertEq(ERC4626ExtendedDecimalsOffsetEOA.decimals(), 18 + 3); - assertEq( - ERC4626ExtendedDecimalsOffsetEOA.asset(), - makeAddr("someAccount") - ); + assertEq(ERC4626ExtendedDecimalsOffsetEOA.asset(), makeAddr("someAccount")); /** * @dev Check the case where success is `False`. */ - bytes memory argsDecimalsOffsetNoDecimals = abi.encode( - _NAME, - _SYMBOL, - deployer, - _DECIMALS_OFFSET + 6, - _NAME_EIP712, - _VERSION_EIP712 - ); + bytes memory argsDecimalsOffsetNoDecimals = + abi.encode(_NAME, _SYMBOL, deployer, _DECIMALS_OFFSET + 6, _NAME_EIP712, _VERSION_EIP712); // solhint-disable-next-line var-name-mixedcase - IERC4626Extended ERC4626ExtendedDecimalsOffsetNoDecimals = IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffsetNoDecimals - ) - ); + IERC4626Extended ERC4626ExtendedDecimalsOffsetNoDecimals = + IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetNoDecimals)); assertEq(ERC4626ExtendedDecimalsOffsetNoDecimals.name(), _NAME); assertEq(ERC4626ExtendedDecimalsOffsetNoDecimals.symbol(), _SYMBOL); assertEq(ERC4626ExtendedDecimalsOffsetNoDecimals.decimals(), 18 + 6); @@ -237,59 +147,26 @@ contract ERC4626VaultTest is ERC4626Test { * @dev Check the case where the return value is above the * maximum value of the type `uint8`. */ - address erc20ExcessDecimalsMock = address( - new ERC20ExcessDecimalsMock() - ); - bytes memory argsDecimalsOffsetTooHighDecimals = abi.encode( - _NAME, - _SYMBOL, - erc20ExcessDecimalsMock, - _DECIMALS_OFFSET + 9, - _NAME_EIP712, - _VERSION_EIP712 - ); + address erc20ExcessDecimalsMock = address(new ERC20ExcessDecimalsMock()); + bytes memory argsDecimalsOffsetTooHighDecimals = + abi.encode(_NAME, _SYMBOL, erc20ExcessDecimalsMock, _DECIMALS_OFFSET + 9, _NAME_EIP712, _VERSION_EIP712); // solhint-disable-next-line var-name-mixedcase IERC4626Extended ERC4626ExtendedDecimalsOffsetTooHighDecimals = IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffsetTooHighDecimals - ) - ); - assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.name(), _NAME); - assertEq( - ERC4626ExtendedDecimalsOffsetTooHighDecimals.symbol(), - _SYMBOL - ); - assertEq( - ERC4626ExtendedDecimalsOffsetTooHighDecimals.decimals(), - 18 + 9 - ); - assertEq( - ERC4626ExtendedDecimalsOffsetTooHighDecimals.asset(), - erc20ExcessDecimalsMock + vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetTooHighDecimals) ); + assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.name(), _NAME); + assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.symbol(), _SYMBOL); + assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.decimals(), 18 + 9); + assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.asset(), erc20ExcessDecimalsMock); /** * @dev Check the case where calculated `decimals` value overflows * the `uint8` type. */ - bytes memory argsDecimalsOffsetOverflow = abi.encode( - _NAME, - _SYMBOL, - underlying, - type(uint8).max, - _NAME_EIP712, - _VERSION_EIP712 - ); + bytes memory argsDecimalsOffsetOverflow = + abi.encode(_NAME, _SYMBOL, underlying, type(uint8).max, _NAME_EIP712, _VERSION_EIP712); vm.expectRevert(); - IERC4626Extended( - vyperDeployer.deployContract( - "src/extensions/", - "ERC4626", - argsDecimalsOffsetOverflow - ) - ); + IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetOverflow)); } function testEmptyVaultDeposit() public { @@ -299,153 +176,56 @@ contract ERC4626VaultTest is ERC4626Test { uint256 shares = 1; vm.startPrank(holder); underlying.mint(holder, type(uint16).max); - underlying.approve( - ERC4626ExtendedDecimalsOffset0Addr, - type(uint256).max - ); - underlying.approve( - ERC4626ExtendedDecimalsOffset6Addr, - type(uint256).max - ); - underlying.approve( - ERC4626ExtendedDecimalsOffset12Addr, - type(uint256).max - ); - underlying.approve( - ERC4626ExtendedDecimalsOffset18Addr, - type(uint256).max - ); + underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint256).max); + underlying.approve(ERC4626ExtendedDecimalsOffset6Addr, type(uint256).max); + underlying.approve(ERC4626ExtendedDecimalsOffset12Addr, type(uint256).max); + underlying.approve(ERC4626ExtendedDecimalsOffset18Addr, type(uint256).max); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.maxDeposit(holder), - type(uint256).max - ); + assertEq(ERC4626ExtendedDecimalsOffset0.maxDeposit(holder), type(uint256).max); assertEq(ERC4626ExtendedDecimalsOffset0.previewDeposit(assets), shares); assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset6.maxDeposit(holder), - type(uint256).max - ); - assertEq( - ERC4626ExtendedDecimalsOffset6.previewDeposit(assets), - shares * 10 ** 6 - ); + assertEq(ERC4626ExtendedDecimalsOffset6.maxDeposit(holder), type(uint256).max); + assertEq(ERC4626ExtendedDecimalsOffset6.previewDeposit(assets), shares * 10 ** 6); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset12.maxDeposit(holder), - type(uint256).max - ); - assertEq( - ERC4626ExtendedDecimalsOffset12.previewDeposit(assets), - shares * 10 ** 12 - ); + assertEq(ERC4626ExtendedDecimalsOffset12.maxDeposit(holder), type(uint256).max); + assertEq(ERC4626ExtendedDecimalsOffset12.previewDeposit(assets), shares * 10 ** 12); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset18.maxDeposit(holder), - type(uint256).max - ); - assertEq( - ERC4626ExtendedDecimalsOffset18.previewDeposit(assets), - shares * 10 ** 18 - ); + assertEq(ERC4626ExtendedDecimalsOffset18.maxDeposit(holder), type(uint256).max); + assertEq(ERC4626ExtendedDecimalsOffset18.previewDeposit(assets), shares * 10 ** 18); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset0Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset0Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(zeroAddress, receiver, shares); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Deposit(holder, receiver, assets, shares); ERC4626ExtendedDecimalsOffset0.deposit(assets, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset6Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset6Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 6); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 6); ERC4626ExtendedDecimalsOffset6.deposit(assets, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset12Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset12Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 12); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 12); ERC4626ExtendedDecimalsOffset12.deposit(assets, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset18Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset18Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 18); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 18); ERC4626ExtendedDecimalsOffset18.deposit(assets, receiver); @@ -457,36 +237,18 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(holder), 0); - assertEq( - ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), - shares * 10 ** 6 - ); - assertEq( - ERC4626ExtendedDecimalsOffset6.totalSupply(), - shares * 10 ** 6 - ); + assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), shares * 10 ** 6); + assertEq(ERC4626ExtendedDecimalsOffset6.totalSupply(), shares * 10 ** 6); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(holder), 0); - assertEq( - ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), - shares * 10 ** 12 - ); - assertEq( - ERC4626ExtendedDecimalsOffset12.totalSupply(), - shares * 10 ** 12 - ); + assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), shares * 10 ** 12); + assertEq(ERC4626ExtendedDecimalsOffset12.totalSupply(), shares * 10 ** 12); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(holder), 0); - assertEq( - ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), - shares * 10 ** 18 - ); - assertEq( - ERC4626ExtendedDecimalsOffset18.totalSupply(), - shares * 10 ** 18 - ); + assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), shares * 10 ** 18); + assertEq(ERC4626ExtendedDecimalsOffset18.totalSupply(), shares * 10 ** 18); vm.stopPrank(); } @@ -497,153 +259,56 @@ contract ERC4626VaultTest is ERC4626Test { uint256 shares = 1; vm.startPrank(holder); underlying.mint(holder, type(uint16).max); - underlying.approve( - ERC4626ExtendedDecimalsOffset0Addr, - type(uint256).max - ); - underlying.approve( - ERC4626ExtendedDecimalsOffset6Addr, - type(uint256).max - ); - underlying.approve( - ERC4626ExtendedDecimalsOffset12Addr, - type(uint256).max - ); - underlying.approve( - ERC4626ExtendedDecimalsOffset18Addr, - type(uint256).max - ); + underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint256).max); + underlying.approve(ERC4626ExtendedDecimalsOffset6Addr, type(uint256).max); + underlying.approve(ERC4626ExtendedDecimalsOffset12Addr, type(uint256).max); + underlying.approve(ERC4626ExtendedDecimalsOffset18Addr, type(uint256).max); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.maxMint(receiver), - type(uint256).max - ); + assertEq(ERC4626ExtendedDecimalsOffset0.maxMint(receiver), type(uint256).max); assertEq(ERC4626ExtendedDecimalsOffset0.previewMint(shares), assets); assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset6.maxMint(receiver), - type(uint256).max - ); - assertEq( - ERC4626ExtendedDecimalsOffset6.previewMint(shares * 10 ** 6), - assets - ); + assertEq(ERC4626ExtendedDecimalsOffset6.maxMint(receiver), type(uint256).max); + assertEq(ERC4626ExtendedDecimalsOffset6.previewMint(shares * 10 ** 6), assets); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset12.maxMint(receiver), - type(uint256).max - ); - assertEq( - ERC4626ExtendedDecimalsOffset12.previewMint(shares * 10 ** 12), - assets - ); + assertEq(ERC4626ExtendedDecimalsOffset12.maxMint(receiver), type(uint256).max); + assertEq(ERC4626ExtendedDecimalsOffset12.previewMint(shares * 10 ** 12), assets); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), 0); - assertEq( - ERC4626ExtendedDecimalsOffset18.maxMint(receiver), - type(uint256).max - ); - assertEq( - ERC4626ExtendedDecimalsOffset18.previewMint(shares * 10 ** 18), - assets - ); + assertEq(ERC4626ExtendedDecimalsOffset18.maxMint(receiver), type(uint256).max); + assertEq(ERC4626ExtendedDecimalsOffset18.previewMint(shares * 10 ** 18), assets); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset0Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset0Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(zeroAddress, receiver, shares); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Deposit(holder, receiver, assets, shares); ERC4626ExtendedDecimalsOffset0.mint(shares, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset6Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset6Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 6); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 6); ERC4626ExtendedDecimalsOffset6.mint(shares * 10 ** 6, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset12Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset12Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 12); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 12); ERC4626ExtendedDecimalsOffset12.mint(shares * 10 ** 12, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer( - holder, - ERC4626ExtendedDecimalsOffset18Addr, - assets - ); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset18Addr, assets); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 18); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 18); ERC4626ExtendedDecimalsOffset18.mint(shares * 10 ** 18, receiver); @@ -655,36 +320,18 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(holder), 0); - assertEq( - ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), - shares * 10 ** 6 - ); - assertEq( - ERC4626ExtendedDecimalsOffset6.totalSupply(), - shares * 10 ** 6 - ); + assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), shares * 10 ** 6); + assertEq(ERC4626ExtendedDecimalsOffset6.totalSupply(), shares * 10 ** 6); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(holder), 0); - assertEq( - ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), - shares * 10 ** 12 - ); - assertEq( - ERC4626ExtendedDecimalsOffset12.totalSupply(), - shares * 10 ** 12 - ); + assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), shares * 10 ** 12); + assertEq(ERC4626ExtendedDecimalsOffset12.totalSupply(), shares * 10 ** 12); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(holder), 0); - assertEq( - ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), - shares * 10 ** 18 - ); - assertEq( - ERC4626ExtendedDecimalsOffset18.totalSupply(), - shares * 10 ** 18 - ); + assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), shares * 10 ** 18); + assertEq(ERC4626ExtendedDecimalsOffset18.totalSupply(), shares * 10 ** 18); vm.stopPrank(); } @@ -708,83 +355,35 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset18.maxWithdraw(holder), 0); assertEq(ERC4626ExtendedDecimalsOffset18.previewWithdraw(0), 0); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset0.withdraw(0, receiver, holder); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset6Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset6.withdraw(0, receiver, holder); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset12Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset12.withdraw(0, receiver, holder); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset18Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset18.withdraw(0, receiver, holder); @@ -831,83 +430,35 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset18.maxRedeem(holder), 0); assertEq(ERC4626ExtendedDecimalsOffset18.previewRedeem(0), 0); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset0.redeem(0, receiver, holder); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset6Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset6Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset6Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset6.redeem(0, receiver, holder); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset12Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset12Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset12Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset12.redeem(0, receiver, holder); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset18Addr, receiver, 0); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset18Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset18Addr); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset18.redeem(0, receiver, holder); @@ -946,89 +497,39 @@ contract ERC4626VaultTest is ERC4626Test { vm.startPrank(alice); underlying.mint(alice, assets); underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, assets); - assertEq( - underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), - assets - ); + assertEq(underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), assets); uint256 alicePreDepositBalance = underlying.balanceOf(alice); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(alice, ERC4626ExtendedDecimalsOffset0Addr, assets); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(zeroAddress, alice, assets); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Deposit(alice, alice, assets, assets); - uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0.deposit( - assets, - alice - ); + uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0.deposit(assets, alice); assertEq(assets, aliceShareAmount); - assertEq( - ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceShareAmount), - assets - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.previewDeposit(assets), - aliceShareAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.totalSupply(), - aliceShareAmount - ); + assertEq(ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceShareAmount), assets); + assertEq(ERC4626ExtendedDecimalsOffset0.previewDeposit(assets), aliceShareAmount); + assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), aliceShareAmount); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), assets); + assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice), - aliceShareAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - assets + ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), assets ); assertEq(underlying.balanceOf(alice), alicePreDepositBalance - assets); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(alice, zeroAddress, assets); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, alice, assets); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Withdraw(alice, alice, alice, assets, assets); ERC4626ExtendedDecimalsOffset0.withdraw(assets, alice, alice); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 0 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); assertEq(underlying.balanceOf(alice), alicePreDepositBalance); vm.stopPrank(); } @@ -1043,89 +544,39 @@ contract ERC4626VaultTest is ERC4626Test { vm.startPrank(alice); underlying.mint(alice, shares); underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, shares); - assertEq( - underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), - shares - ); + assertEq(underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), shares); uint256 alicePreDepositBalance = underlying.balanceOf(alice); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(alice, ERC4626ExtendedDecimalsOffset0Addr, shares); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(zeroAddress, alice, shares); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Deposit(alice, alice, shares, shares); - uint256 aliceAssetAmount = ERC4626ExtendedDecimalsOffset0.mint( - shares, - alice - ); + uint256 aliceAssetAmount = ERC4626ExtendedDecimalsOffset0.mint(shares, alice); assertEq(aliceAssetAmount, shares); - assertEq( - ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceAssetAmount), - shares - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.previewDeposit(shares), - aliceAssetAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.totalSupply(), - aliceAssetAmount - ); + assertEq(ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceAssetAmount), shares); + assertEq(ERC4626ExtendedDecimalsOffset0.previewDeposit(shares), aliceAssetAmount); + assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), aliceAssetAmount); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), shares); + assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceAssetAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice), - aliceAssetAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - shares + ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), shares ); assertEq(underlying.balanceOf(alice), alicePreDepositBalance - shares); - vm.expectEmit( - true, - true, - false, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC20.Transfer(alice, zeroAddress, shares); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, alice, shares); - vm.expectEmit( - true, - true, - true, - true, - ERC4626ExtendedDecimalsOffset0Addr - ); + vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); emit IERC4626.Withdraw(alice, alice, alice, shares, shares); ERC4626ExtendedDecimalsOffset0.redeem(shares, alice, alice); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 0 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); assertEq(underlying.balanceOf(alice), alicePreDepositBalance); vm.stopPrank(); } @@ -1142,82 +593,47 @@ contract ERC4626VaultTest is ERC4626Test { uint256 mutationUnderlyingAmount = 3_000; vm.startPrank(alice); underlying.mint(alice, initialAmountAlice); - underlying.approve( - ERC4626ExtendedDecimalsOffset0Addr, - initialAmountAlice - ); - assertEq( - underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), - initialAmountAlice - ); + underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, initialAmountAlice); + assertEq(underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), initialAmountAlice); vm.stopPrank(); vm.startPrank(bob); underlying.mint(bob, initialAmountBob); - underlying.approve( - ERC4626ExtendedDecimalsOffset0Addr, - initialAmountBob - ); - assertEq( - underlying.allowance(bob, ERC4626ExtendedDecimalsOffset0Addr), - initialAmountBob - ); + underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, initialAmountBob); + assertEq(underlying.allowance(bob, ERC4626ExtendedDecimalsOffset0Addr), initialAmountBob); vm.stopPrank(); /** * @dev 1. Alice mints 2,000 shares (costs 2,000 tokens). */ vm.startPrank(alice); - uint256 aliceUnderlyingAmount = ERC4626ExtendedDecimalsOffset0.mint( - 2_000, - alice - ); - uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0 - .previewDeposit(aliceUnderlyingAmount); + uint256 aliceUnderlyingAmount = ERC4626ExtendedDecimalsOffset0.mint(2_000, alice); + uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0.previewDeposit(aliceUnderlyingAmount); assertEq(aliceShareAmount, 2_000); + assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice), - aliceShareAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), + ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), aliceUnderlyingAmount ); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToShares( - aliceUnderlyingAmount - ), + ERC4626ExtendedDecimalsOffset0.convertToShares(aliceUnderlyingAmount), ERC4626ExtendedDecimalsOffset0.balanceOf(alice) ); assertEq(aliceUnderlyingAmount, 2_000); - assertEq( - ERC4626ExtendedDecimalsOffset0.totalSupply(), - aliceShareAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.totalAssets(), - aliceUnderlyingAmount - ); + assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), aliceShareAmount); + assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), aliceUnderlyingAmount); vm.stopPrank(); /** * @dev 2. Bob deposits 4,000 tokens (mints 4,000 shares). */ vm.startPrank(bob); - uint256 bobShareAmount = ERC4626ExtendedDecimalsOffset0.deposit( - 4_000, - bob - ); - uint256 bobUnderlyingAmount = ERC4626ExtendedDecimalsOffset0 - .previewWithdraw(bobShareAmount); + uint256 bobShareAmount = ERC4626ExtendedDecimalsOffset0.deposit(4_000, bob); + uint256 bobUnderlyingAmount = ERC4626ExtendedDecimalsOffset0.previewWithdraw(bobShareAmount); assertEq(bobUnderlyingAmount, 4_000); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), bobShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), + ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), bobUnderlyingAmount ); assertEq( @@ -1227,10 +643,7 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(bobShareAmount, bobUnderlyingAmount); uint256 preMutationShareBal = aliceShareAmount + bobShareAmount; uint256 preMutationBal = aliceUnderlyingAmount + bobUnderlyingAmount; - assertEq( - ERC4626ExtendedDecimalsOffset0.totalSupply(), - preMutationShareBal - ); + assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), preMutationShareBal); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), preMutationBal); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 6_000); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 6_000); @@ -1239,33 +652,17 @@ contract ERC4626VaultTest is ERC4626Test { /** * @dev 3. Vault mutates by +3,000 tokens (simulated yield returned from strategy). */ - underlying.mint( - ERC4626ExtendedDecimalsOffset0Addr, - mutationUnderlyingAmount - ); + underlying.mint(ERC4626ExtendedDecimalsOffset0Addr, mutationUnderlyingAmount); + assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), preMutationShareBal); + assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), preMutationBal + mutationUnderlyingAmount); + assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.totalSupply(), - preMutationShareBal - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.totalAssets(), - preMutationBal + mutationUnderlyingAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice), - aliceShareAmount - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), + ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), aliceUnderlyingAmount + (mutationUnderlyingAmount / 3) * 1 - 1 ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), bobShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), + ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), bobUnderlyingAmount + (mutationUnderlyingAmount / 3) * 2 - 1 ); @@ -1276,19 +673,9 @@ contract ERC4626VaultTest is ERC4626Test { ERC4626ExtendedDecimalsOffset0.deposit(2_000, alice); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 7_333); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 3_333); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 4_999 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 4_999); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 4_000); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), - 6_000 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 6_000); vm.stopPrank(); /** @@ -1300,19 +687,9 @@ contract ERC4626VaultTest is ERC4626Test { ERC4626ExtendedDecimalsOffset0.mint(2_000, bob); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 9_333); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 3_333); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 4_999 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 4_999); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 6_000); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), - 9_000 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 9_000); assertEq(underlying.balanceOf(alice), 0); assertEq(underlying.balanceOf(bob), 1); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 14_000); @@ -1321,23 +698,10 @@ contract ERC4626VaultTest is ERC4626Test { /** * @dev 6. Vault mutates by +3,000 tokens. */ - underlying.mint( - ERC4626ExtendedDecimalsOffset0Addr, - mutationUnderlyingAmount - ); + underlying.mint(ERC4626ExtendedDecimalsOffset0Addr, mutationUnderlyingAmount); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 17_000); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 6_070 - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), - 10_928 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 6_070); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 10_928); /** * @dev 7. Alice redeems 1,333 shares (2,427 assets). @@ -1348,19 +712,9 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 8_000); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 14_573); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 2_000); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 3_643 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 3_643); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 6_000); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), - 10_929 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 10_929); vm.stopPrank(); /** @@ -1372,19 +726,9 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 6_392); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 11_644); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 2_000); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 3_643 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 3_643); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 4_392); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), - 8_000 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 8_000); vm.stopPrank(); /** @@ -1397,19 +741,9 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 4_392); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 8_001); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 0 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 4_392); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), - 8_000 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 8_000); vm.stopPrank(); /** @@ -1421,33 +755,17 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 1); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(alice) - ), - 0 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(bob) - ), - 0 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 0); assertEq(underlying.balanceOf(ERC4626ExtendedDecimalsOffset0Addr), 1); vm.stopPrank(); } function testDepositInsufficientAllowance() public { underlying.mint(self, type(uint8).max); - underlying.approve( - ERC4626ExtendedDecimalsOffset0Addr, - type(uint8).max - 1 - ); - assertEq( - underlying.allowance(self, ERC4626ExtendedDecimalsOffset0Addr), - type(uint8).max - 1 - ); + underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint8).max - 1); + assertEq(underlying.allowance(self, ERC4626ExtendedDecimalsOffset0Addr), type(uint8).max - 1); vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientAllowance.selector, @@ -1464,11 +782,7 @@ contract ERC4626VaultTest is ERC4626Test { underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint8).max); ERC4626ExtendedDecimalsOffset0.deposit(type(uint8).max, self); vm.expectRevert(bytes("ERC4626: withdraw more than maximum")); - ERC4626ExtendedDecimalsOffset0.withdraw( - uint256(type(uint8).max) + 1, - self, - self - ); + ERC4626ExtendedDecimalsOffset0.withdraw(uint256(type(uint8).max) + 1, self, self); } function testWithdrawInsufficientAllowance() public { @@ -1485,11 +799,7 @@ contract ERC4626VaultTest is ERC4626Test { underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint8).max); ERC4626ExtendedDecimalsOffset0.deposit(type(uint8).max, self); vm.expectRevert(bytes("ERC4626: redeem more than maximum")); - ERC4626ExtendedDecimalsOffset0.redeem( - uint256(type(uint8).max) + 1, - self, - self - ); + ERC4626ExtendedDecimalsOffset0.redeem(uint256(type(uint8).max) + 1, self, self); } function testWithdrawWithNoAssets() public { @@ -1505,10 +815,7 @@ contract ERC4626VaultTest is ERC4626Test { function testDepositWithNoApproval() public { vm.expectRevert( abi.encodeWithSelector( - IERC20Errors.ERC20InsufficientAllowance.selector, - ERC4626ExtendedDecimalsOffset0Addr, - 0, - type(uint8).max + IERC20Errors.ERC20InsufficientAllowance.selector, ERC4626ExtendedDecimalsOffset0Addr, 0, type(uint8).max ) ); ERC4626ExtendedDecimalsOffset0.deposit(type(uint8).max, self); @@ -1517,10 +824,7 @@ contract ERC4626VaultTest is ERC4626Test { function testMintWithNoApproval() public { vm.expectRevert( abi.encodeWithSelector( - IERC20Errors.ERC20InsufficientAllowance.selector, - ERC4626ExtendedDecimalsOffset0Addr, - 0, - type(uint8).max + IERC20Errors.ERC20InsufficientAllowance.selector, ERC4626ExtendedDecimalsOffset0Addr, 0, type(uint8).max ) ); ERC4626ExtendedDecimalsOffset0.mint(type(uint8).max, self); @@ -1529,12 +833,7 @@ contract ERC4626VaultTest is ERC4626Test { function testDepositZero() public { ERC4626ExtendedDecimalsOffset0.deposit(0, self); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(self), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(self) - ), - 0 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(self)), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); } @@ -1542,12 +841,7 @@ contract ERC4626VaultTest is ERC4626Test { function testMintZero() public { ERC4626ExtendedDecimalsOffset0.mint(0, self); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(self), 0); - assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets( - ERC4626ExtendedDecimalsOffset0.balanceOf(self) - ), - 0 - ); + assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(self)), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); } @@ -1598,42 +892,21 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 - .DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); vm.expectEmit(true, true, false, true); emit IERC20.Approval(owner, spender, amount); - ERC4626ExtendedDecimalsOffset0.permit( - owner, - spender, - amount, - deadline, - v, - r, - s - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.allowance(owner, spender), - amount - ); + ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); + assertEq(ERC4626ExtendedDecimalsOffset0.allowance(owner, spender), amount); assertEq(ERC4626ExtendedDecimalsOffset0.nonces(owner), 1); } @@ -1644,48 +917,22 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 - .DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); vm.expectEmit(true, true, false, true); emit IERC20.Approval(owner, spender, amount); - ERC4626ExtendedDecimalsOffset0.permit( - owner, - spender, - amount, - deadline, - v, - r, - s - ); + ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit( - owner, - spender, - amount, - deadline, - v, - r, - s - ); + ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); } function testPermitOtherSignature() public { @@ -1695,37 +942,19 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 - .DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key + 1, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit( - owner, - spender, - amount, - deadline, - v, - r, - s - ); + ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); } function testPermitBadChainId() public { @@ -1750,29 +979,12 @@ contract ERC4626VaultTest is ERC4626Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit( - owner, - spender, - amount, - deadline, - v, - r, - s - ); + ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); } function testPermitBadNonce() public { @@ -1782,37 +994,19 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = 1; // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 - .DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit( - owner, - spender, - amount, - deadline, - v, - r, - s - ); + ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); } function testPermitExpiredDeadline() public { @@ -1822,44 +1016,23 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp - 1; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 - .DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); vm.expectRevert(bytes("ERC20Permit: expired deadline")); - ERC4626ExtendedDecimalsOffset0.permit( - owner, - spender, - amount, - deadline, - v, - r, - s - ); + ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); } function testCachedDomainSeparator() public { - assertEq( - ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), - _CACHED_DOMAIN_SEPARATOR - ); + assertEq(ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), _CACHED_DOMAIN_SEPARATOR); } function testDomainSeparator() public { @@ -1895,113 +1068,58 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), digest); } - function testFuzzPermitSuccess( - string calldata owner, - string calldata spender, - uint16 increment - ) public { + function testFuzzPermitSuccess(string calldata owner, string calldata spender, uint16 increment) public { (address ownerAddr, uint256 key) = makeAddrAndKey(owner); address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 - .DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - ownerAddr, - spenderAddr, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) ) ) ); vm.expectEmit(true, true, false, true); emit IERC20.Approval(ownerAddr, spenderAddr, amount); - ERC4626ExtendedDecimalsOffset0.permit( - ownerAddr, - spenderAddr, - amount, - deadline, - v, - r, - s - ); - assertEq( - ERC4626ExtendedDecimalsOffset0.allowance(ownerAddr, spenderAddr), - amount - ); + ERC4626ExtendedDecimalsOffset0.permit(ownerAddr, spenderAddr, amount, deadline, v, r, s); + assertEq(ERC4626ExtendedDecimalsOffset0.allowance(ownerAddr, spenderAddr), amount); assertEq(ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr), 1); } - function testFuzzPermitInvalid( - string calldata owner, - string calldata spender, - uint16 increment - ) public { - vm.assume( - keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong")) - ); - (address ownerAddr, ) = makeAddrAndKey(owner); + function testFuzzPermitInvalid(string calldata owner, string calldata spender, uint16 increment) public { + vm.assume(keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong"))); + (address ownerAddr,) = makeAddrAndKey(owner); (, uint256 keyWrong) = makeAddrAndKey("ownerWrong"); address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 - .DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( keyWrong, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - ownerAddr, - spenderAddr, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit( - ownerAddr, - spenderAddr, - amount, - deadline, - v, - r, - s - ); + ERC4626ExtendedDecimalsOffset0.permit(ownerAddr, spenderAddr, amount, deadline, v, r, s); } function testFuzzDomainSeparator(uint8 increment) public { @@ -2024,11 +1142,7 @@ contract ERC4626VaultTest is ERC4626Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume( - randomHex != hex"0f" && - randomSalt != bytes32(0) && - randomExtensions.length != 0 - ); + vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -2045,19 +1159,10 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, ERC4626ExtendedDecimalsOffset0Addr); assertTrue(salt != randomSalt); - assertTrue( - keccak256(abi.encode(extensions)) != - keccak256(abi.encode(randomExtensions)) - ); + assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), digest); } @@ -2076,46 +1181,26 @@ contract ERC4626VaultInvariants is Test { VyperDeployer private vyperDeployer = new VyperDeployer(); address private deployer = address(vyperDeployer); ERC20Mock private underlying = - new ERC20Mock( - _NAME_UNDERLYING, - _SYMBOL_UNDERLYING, - deployer, - _INITIAL_SUPPLY_UNDERLYING - ); + new ERC20Mock(_NAME_UNDERLYING, _SYMBOL_UNDERLYING, deployer, _INITIAL_SUPPLY_UNDERLYING); // solhint-disable-next-line var-name-mixedcase IERC4626Extended private ERC4626Extended; ERC4626VaultHandler private erc4626VaultHandler; function setUp() public { - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - underlying, - _DECIMALS_OFFSET, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC4626Extended = IERC4626Extended( - vyperDeployer.deployContract("src/extensions/", "ERC4626", args) - ); + bytes memory args = abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET, _NAME_EIP712, _VERSION_EIP712); + ERC4626Extended = IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", args)); erc4626VaultHandler = new ERC4626VaultHandler(ERC4626Extended); targetContract(address(erc4626VaultHandler)); targetSender(deployer); } function invariantTotalSupply() public { - assertEq( - ERC4626Extended.totalSupply(), - erc4626VaultHandler.totalSupply() - ); + assertEq(ERC4626Extended.totalSupply(), erc4626VaultHandler.totalSupply()); } function invariantTotalAssets() public { - assertEq( - ERC4626Extended.totalAssets(), - erc4626VaultHandler.totalAssets() - ); + assertEq(ERC4626Extended.totalAssets(), erc4626VaultHandler.totalAssets()); } } @@ -2141,15 +1226,9 @@ contract ERC4626VaultHandler { vault.transferFrom(owner, to, amount); } - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) public { + function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) + public + { vault.permit(owner, spender, value, deadline, v, r, s); } diff --git a/test/extensions/interfaces/IERC2981Extended.sol b/test/extensions/interfaces/IERC2981Extended.sol index 043302c0..c360ab97 100644 --- a/test/extensions/interfaces/IERC2981Extended.sol +++ b/test/extensions/interfaces/IERC2981Extended.sol @@ -4,23 +4,13 @@ pragma solidity ^0.8.23; import {IERC2981} from "openzeppelin/interfaces/IERC2981.sol"; interface IERC2981Extended is IERC2981 { - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - function set_default_royalty( - address receiver, - uint96 feeNumerator - ) external; + function set_default_royalty(address receiver, uint96 feeNumerator) external; function delete_default_royalty() external; - function set_token_royalty( - uint256 tokenId, - address receiver, - uint96 feeNumerator - ) external; + function set_token_royalty(uint256 tokenId, address receiver, uint96 feeNumerator) external; function reset_token_royalty(uint256 tokenId) external; diff --git a/test/extensions/interfaces/IERC4626Extended.sol b/test/extensions/interfaces/IERC4626Extended.sol index 1c225583..ca1a68ea 100644 --- a/test/extensions/interfaces/IERC4626Extended.sol +++ b/test/extensions/interfaces/IERC4626Extended.sol @@ -7,9 +7,4 @@ import {IERC4626} from "openzeppelin/interfaces/IERC4626.sol"; import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; // solhint-disable-next-line no-empty-blocks -interface IERC4626Extended is - IERC20Metadata, - IERC20Permit, - IERC4626, - IERC5267 -{} +interface IERC4626Extended is IERC20Metadata, IERC20Permit, IERC4626, IERC5267 {} diff --git a/test/tokens/ERC1155.t.sol b/test/tokens/ERC1155.t.sol index ac4ae342..9c20735a 100644 --- a/test/tokens/ERC1155.t.sol +++ b/test/tokens/ERC1155.t.sol @@ -30,65 +30,38 @@ contract ERC1155Test is Test { function setUp() public { bytes memory args = abi.encode(_BASE_URI); - ERC1155Extended = IERC1155Extended( - vyperDeployer.deployContract("src/tokens/", "ERC1155", args) - ); + ERC1155Extended = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); } function testInitialSetup() public { assertEq(ERC1155Extended.owner(), deployer); assertTrue(ERC1155Extended.is_minter(deployer)); - assertEq( - ERC1155Extended.uri(0), - string.concat(_BASE_URI, Strings.toString(uint256(0))) - ); - assertEq( - ERC1155Extended.uri(1), - string.concat(_BASE_URI, Strings.toString(uint256(1))) - ); + assertEq(ERC1155Extended.uri(0), string.concat(_BASE_URI, Strings.toString(uint256(0)))); + assertEq(ERC1155Extended.uri(1), string.concat(_BASE_URI, Strings.toString(uint256(1)))); vm.expectEmit(true, true, false, false); emit IERC1155Extended.OwnershipTransferred(zeroAddress, deployer); vm.expectEmit(true, false, false, true); emit IERC1155Extended.RoleMinterChanged(deployer, true); bytes memory args = abi.encode(_BASE_URI); - ERC1155ExtendedInitialEvent = IERC1155Extended( - vyperDeployer.deployContract("src/tokens/", "ERC1155", args) - ); + ERC1155ExtendedInitialEvent = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); assertEq(ERC1155ExtendedInitialEvent.owner(), deployer); assertTrue(ERC1155ExtendedInitialEvent.is_minter(deployer)); - assertEq( - ERC1155ExtendedInitialEvent.uri(0), - string.concat(_BASE_URI, Strings.toString(uint256(0))) - ); - assertEq( - ERC1155ExtendedInitialEvent.uri(1), - string.concat(_BASE_URI, Strings.toString(uint256(1))) - ); + assertEq(ERC1155ExtendedInitialEvent.uri(0), string.concat(_BASE_URI, Strings.toString(uint256(0)))); + assertEq(ERC1155ExtendedInitialEvent.uri(1), string.concat(_BASE_URI, Strings.toString(uint256(1)))); } function testSupportsInterfaceSuccess() public { - assertTrue( - ERC1155Extended.supportsInterface(type(IERC165).interfaceId) - ); - assertTrue( - ERC1155Extended.supportsInterface(type(IERC1155).interfaceId) - ); - assertTrue( - ERC1155Extended.supportsInterface( - type(IERC1155MetadataURI).interfaceId - ) - ); + assertTrue(ERC1155Extended.supportsInterface(type(IERC165).interfaceId)); + assertTrue(ERC1155Extended.supportsInterface(type(IERC1155).interfaceId)); + assertTrue(ERC1155Extended.supportsInterface(type(IERC1155MetadataURI).interfaceId)); } function testSupportsInterfaceSuccessGasCost() public { uint256 startGas = gasleft(); ERC1155Extended.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && - ERC1155Extended.supportsInterface(type(IERC165).interfaceId) - ); + assertTrue(gasUsed <= 30_000 && ERC1155Extended.supportsInterface(type(IERC165).interfaceId)); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -99,9 +72,7 @@ contract ERC1155Test is Test { uint256 startGas = gasleft(); ERC1155Extended.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && !ERC1155Extended.supportsInterface(0x0011bbff) - ); + assertTrue(gasUsed <= 30_000 && !ERC1155Extended.supportsInterface(0x0011bbff)); } function testBalanceOfCase1() public { @@ -116,10 +87,7 @@ contract ERC1155Test is Test { ERC1155Extended.safe_mint(firstOwner, id1, amountFirstOwner, data); ERC1155Extended.safe_mint(secondOwner, id2, amountSecondOwner, data); assertEq(ERC1155Extended.balanceOf(firstOwner, id1), amountFirstOwner); - assertEq( - ERC1155Extended.balanceOf(secondOwner, id2), - amountSecondOwner - ); + assertEq(ERC1155Extended.balanceOf(secondOwner, id2), amountSecondOwner); assertEq(ERC1155Extended.balanceOf(firstOwner, 2), 0); vm.stopPrank(); } @@ -384,27 +352,17 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert( - bytes("ERC1155: caller is not token owner or approved") - ); + vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); ERC1155Extended.safeTransferFrom(owner, receiver, id1, amount1, data); vm.stopPrank(); } function testSafeTransferFromNoData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -453,18 +411,10 @@ contract ERC1155Test is Test { function testSafeTransferFromWithData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -514,15 +464,9 @@ contract ERC1155Test is Test { function testSafeTransferFromReceiverInvalidReturnIdentifier() public { address owner = makeAddr("owner"); bytes4 receiverSingleMagicValue = 0x00bb8833; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -535,9 +479,7 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert( - bytes("ERC1155: transfer to non-ERC1155Receiver implementer") - ); + vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); ERC1155Extended.safeTransferFrom(owner, receiver, id1, amount1, data); vm.stopPrank(); @@ -550,27 +492,17 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert( - bytes("ERC1155: transfer to non-ERC1155Receiver implementer") - ); + vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); ERC1155Extended.safeTransferFrom(owner, receiver, id2, amount2, data); vm.stopPrank(); } function testSafeTransferFromReceiverReverts() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - true, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -643,13 +575,7 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC1155: insufficient balance for transfer")); - ERC1155Extended.safeTransferFrom( - owner, - makeAddr("to"), - id, - ++amount, - data - ); + ERC1155Extended.safeTransferFrom(owner, makeAddr("to"), id, ++amount, data); vm.stopPrank(); } @@ -691,13 +617,7 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -736,13 +656,7 @@ contract ERC1155Test is Test { vm.startPrank(operator); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(operator, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -773,33 +687,17 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert( - bytes("ERC1155: caller is not token owner or approved") - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); vm.stopPrank(); } function testSafeBatchTransferFromNoData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -822,20 +720,8 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived( - owner, - owner, - ids, - amounts, - data - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -845,18 +731,10 @@ contract ERC1155Test is Test { function testSafeBatchTransferFromWithData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -879,20 +757,8 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived( - owner, - owner, - ids, - amounts, - data - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -902,16 +768,10 @@ contract ERC1155Test is Test { function testSafeBatchTransferFromReceiverInvalidReturnIdentifier() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -931,31 +791,17 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert( - bytes("ERC1155: transfer to non-ERC1155Receiver implementer") - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); vm.stopPrank(); } function testSafeBatchTransferFromReceiverReverts() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - true - ); + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, true); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -975,16 +821,8 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert( - bytes("ERC1155ReceiverMock: reverting on batch receive") - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + vm.expectRevert(bytes("ERC1155ReceiverMock: reverting on batch receive")); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); vm.stopPrank(); } @@ -1009,30 +847,16 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(); - ERC1155Extended.safeBatchTransferFrom( - owner, - deployer, - ids, - amounts, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, deployer, ids, amounts, data); vm.stopPrank(); } function testSafeBatchTransferFromReceiverRevertsOnlySingle() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - true, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -1055,20 +879,8 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived( - owner, - owner, - ids, - amounts, - data - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -1098,13 +910,7 @@ contract ERC1155Test is Test { vm.startPrank(owner); ++amounts[3]; vm.expectRevert(bytes("ERC1155: insufficient balance for transfer")); - ERC1155Extended.safeBatchTransferFrom( - owner, - makeAddr("to"), - ids, - amounts, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, makeAddr("to"), ids, amounts, data); vm.stopPrank(); } @@ -1134,21 +940,9 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC1155: ids and amounts length mismatch")); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids1, - amounts1, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids1, amounts1, data); vm.expectRevert(bytes("ERC1155: ids and amounts length mismatch")); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids2, - amounts2, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids2, amounts2, data); vm.stopPrank(); } @@ -1173,32 +967,18 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC1155: transfer to the zero address")); - ERC1155Extended.safeBatchTransferFrom( - owner, - zeroAddress, - ids, - amounts, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, zeroAddress, ids, amounts, data); vm.stopPrank(); } function testUriNoTokenUri() public { - assertEq( - ERC1155Extended.uri(0), - string.concat(_BASE_URI, Strings.toString(uint256(0))) - ); - assertEq( - ERC1155Extended.uri(1), - string.concat(_BASE_URI, Strings.toString(uint256(1))) - ); + assertEq(ERC1155Extended.uri(0), string.concat(_BASE_URI, Strings.toString(uint256(0)))); + assertEq(ERC1155Extended.uri(1), string.concat(_BASE_URI, Strings.toString(uint256(1)))); } function testUriNoBaseURI() public { bytes memory args = abi.encode(""); - ERC1155ExtendedNoBaseURI = IERC1155Extended( - vyperDeployer.deployContract("src/tokens/", "ERC1155", args) - ); + ERC1155ExtendedNoBaseURI = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); string memory uri = "my_awesome_uri"; uint256 id = 1; vm.prank(deployer); @@ -1216,9 +996,7 @@ contract ERC1155Test is Test { function testUriBaseAndTokenUriNotSet() public { bytes memory args = abi.encode(""); - ERC1155ExtendedNoBaseURI = IERC1155Extended( - vyperDeployer.deployContract("src/tokens/", "ERC1155", args) - ); + ERC1155ExtendedNoBaseURI = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); uint256 id = 1; assertEq(ERC1155ExtendedNoBaseURI.uri(id), ""); } @@ -1238,15 +1016,9 @@ contract ERC1155Test is Test { uint256 id = 1; vm.prank(deployer); vm.expectEmit(true, false, false, true); - emit IERC1155.URI( - string.concat(_BASE_URI, Strings.toString(uint256(id))), - id - ); + emit IERC1155.URI(string.concat(_BASE_URI, Strings.toString(uint256(id))), id); ERC1155Extended.set_uri(id, uri); - assertEq( - ERC1155Extended.uri(id), - string.concat(_BASE_URI, Strings.toString(uint256(id))) - ); + assertEq(ERC1155Extended.uri(id), string.concat(_BASE_URI, Strings.toString(uint256(id)))); } function testSetUriNonMinter() public { @@ -1283,12 +1055,7 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch( - makeAddr("owner"), - ids, - amounts, - new bytes(0) - ); + ERC1155Extended.safe_mint_batch(makeAddr("owner"), ids, amounts, new bytes(0)); assertEq(ERC1155Extended.total_supply(0), 11); assertEq(ERC1155Extended.total_supply(1), 22); vm.stopPrank(); @@ -1363,12 +1130,7 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch( - makeAddr("owner"), - ids, - amounts, - new bytes(0) - ); + ERC1155Extended.safe_mint_batch(makeAddr("owner"), ids, amounts, new bytes(0)); assertTrue(ERC1155Extended.exists(0)); assertTrue(ERC1155Extended.exists(1)); vm.stopPrank(); @@ -1429,13 +1191,7 @@ contract ERC1155Test is Test { vm.startPrank(firstOwner); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - firstOwner, - firstOwner, - zeroAddress, - id, - burnAmount - ); + emit IERC1155.TransferSingle(firstOwner, firstOwner, zeroAddress, id, burnAmount); ERC1155Extended.burn(firstOwner, id, 10); assertEq(ERC1155Extended.total_supply(0), 25); assertEq(ERC1155Extended.balanceOf(firstOwner, id), 5); @@ -1466,13 +1222,7 @@ contract ERC1155Test is Test { vm.startPrank(operator); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - operator, - owner, - zeroAddress, - id1, - burnAmount - ); + emit IERC1155.TransferSingle(operator, owner, zeroAddress, id1, burnAmount); ERC1155Extended.burn(owner, id1, burnAmount); assertEq(ERC1155Extended.total_supply(id1), amount1 - burnAmount); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1498,9 +1248,7 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert( - bytes("ERC1155: caller is not token owner or approved") - ); + vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); ERC1155Extended.burn(owner, id1, burnAmount); vm.stopPrank(); } @@ -1628,9 +1376,7 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(operator); - vm.expectRevert( - bytes("ERC1155: caller is not token owner or approved") - ); + vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); ERC1155Extended.burn_batch(owner, ids, amounts); vm.stopPrank(); } @@ -1737,23 +1483,11 @@ contract ERC1155Test is Test { bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id1, - amount1 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id2, - amount2 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1763,18 +1497,10 @@ contract ERC1155Test is Test { } function testSafeMintNoData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1783,23 +1509,11 @@ contract ERC1155Test is Test { bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id1, - amount1 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id2, - amount2 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1809,18 +1523,10 @@ contract ERC1155Test is Test { } function testSafeMintWithData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1829,23 +1535,11 @@ contract ERC1155Test is Test { bytes memory data = new bytes(42); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id1, - amount1 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id2, - amount2 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1856,15 +1550,9 @@ contract ERC1155Test is Test { function testSafeMintReceiverInvalidReturnIdentifier() public { bytes4 receiverSingleMagicValue = 0x00bb8833; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1872,31 +1560,19 @@ contract ERC1155Test is Test { uint256 amount2 = 15; bytes memory data = new bytes(0); vm.startPrank(deployer); - vm.expectRevert( - bytes("ERC1155: transfer to non-ERC1155Receiver implementer") - ); + vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); ERC1155Extended.safe_mint(receiver, id1, amount1, data); - vm.expectRevert( - bytes("ERC1155: transfer to non-ERC1155Receiver implementer") - ); + vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); ERC1155Extended.safe_mint(receiver, id2, amount2, data); vm.stopPrank(); } function testSafeMintReceiverReverts() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - true, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1966,13 +1642,7 @@ contract ERC1155Test is Test { bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id, - amount - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id, amount); ERC1155Extended.safe_mint(receiver, id, amount, data); vm.expectRevert(); @@ -1997,13 +1667,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -2013,18 +1677,10 @@ contract ERC1155Test is Test { } function testSafeMintBatchNoData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -2041,13 +1697,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -2057,18 +1707,10 @@ contract ERC1155Test is Test { } function testSafeMintBatchWithData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -2085,13 +1727,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -2101,16 +1737,10 @@ contract ERC1155Test is Test { } function testSafeMintBatchReceiverInvalidReturnIdentifier() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -2126,24 +1756,16 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - vm.expectRevert( - bytes("ERC1155: transfer to non-ERC1155Receiver implementer") - ); + vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); vm.stopPrank(); } function testSafeMintBatchReceiverReverts() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - true - ); + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, true); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -2159,9 +1781,7 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - vm.expectRevert( - bytes("ERC1155ReceiverMock: reverting on batch receive") - ); + vm.expectRevert(bytes("ERC1155ReceiverMock: reverting on batch receive")); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); vm.stopPrank(); } @@ -2187,18 +1807,10 @@ contract ERC1155Test is Test { } function testSafeMintBatchReceiverRevertsOnlySingle() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - true, - receiverBatchMagicValue, - false - ); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -2215,13 +1827,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -2318,13 +1924,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); vm.expectRevert(); @@ -2416,10 +2016,7 @@ contract ERC1155Test is Test { ERC1155Extended.renounce_ownership(); } - function testFuzzSetApprovalForAllSuccess( - address owner, - address operator - ) public { + function testFuzzSetApprovalForAllSuccess(address owner, address operator) public { vm.assume(owner != operator); bool approved = true; assertTrue(!ERC1155Extended.isApprovedForAll(owner, operator)); @@ -2436,10 +2033,7 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSetApprovalForAllRevoke( - address owner, - address operator - ) public { + function testFuzzSetApprovalForAllRevoke(address owner, address operator) public { vm.assume(owner != operator); bool approved = true; assertTrue(!ERC1155Extended.isApprovedForAll(owner, operator)); @@ -2466,11 +2060,8 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && - owner != receiver && - owner.code.length == 0 && - receiver != zeroAddress && - receiver.code.length == 0 + owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress + && receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); vm.startPrank(deployer); @@ -2500,14 +2091,8 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && - owner != receiver && - owner != operator && - owner.code.length == 0 && - receiver != operator && - receiver != zeroAddress && - operator != zeroAddress && - receiver.code.length == 0 + owner != zeroAddress && owner != receiver && owner != operator && owner.code.length == 0 + && receiver != operator && receiver != zeroAddress && operator != zeroAddress && receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); bool approved = true; @@ -2535,32 +2120,14 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeTransferFromNoData( - address owner, - uint256 id1, - uint256 amount1, - uint256 id2, - uint256 amount2 - ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + function testFuzzSafeTransferFromNoData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) + public + { + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); bytes memory data = new bytes(0); @@ -2613,25 +2180,11 @@ contract ERC1155Test is Test { uint256 amount2, bytes calldata data ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); vm.startPrank(deployer); @@ -2685,11 +2238,8 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && - owner != receiver && - owner.code.length == 0 && - receiver != zeroAddress && - receiver.code.length == 0 + owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress + && receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); uint256[] memory ids = new uint256[](2); @@ -2706,13 +2256,7 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2731,14 +2275,8 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && - owner != receiver && - owner != operator && - owner.code.length == 0 && - receiver != operator && - receiver != zeroAddress && - operator != zeroAddress && - receiver.code.length == 0 + owner != zeroAddress && owner != receiver && owner != operator && owner.code.length == 0 + && receiver != operator && receiver != zeroAddress && operator != zeroAddress && receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); bool approved = true; @@ -2763,13 +2301,7 @@ contract ERC1155Test is Test { vm.startPrank(operator); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(operator, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2785,25 +2317,11 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); uint256[] memory ids = new uint256[](2); @@ -2823,20 +2341,8 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived( - owner, - owner, - ids, - amounts, - data - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2851,25 +2357,11 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); /** @@ -2893,20 +2385,8 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived( - owner, - owner, - ids, - amounts, - data - ); - ERC1155Extended.safeBatchTransferFrom( - owner, - receiver, - ids, - amounts, - data - ); + emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2921,19 +2401,10 @@ contract ERC1155Test is Test { ERC1155Extended.set_uri(1, "my_awesome_uri"); } - function testFuzzTotalSupplyAfterSingleMint( - uint256 id, - uint256 amount, - bytes calldata data - ) public { + function testFuzzTotalSupplyAfterSingleMint(uint256 id, uint256 amount, bytes calldata data) public { vm.startPrank(deployer); ERC1155Extended.safe_mint(makeAddr("firstOwner"), id, amount % 2, data); - ERC1155Extended.safe_mint( - makeAddr("secondOwner"), - id, - amount % 2, - data - ); + ERC1155Extended.safe_mint(makeAddr("secondOwner"), id, amount % 2, data); assertEq(ERC1155Extended.total_supply(id), 2 * (amount % 2)); vm.stopPrank(); } @@ -2945,13 +2416,7 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -2961,28 +2426,14 @@ contract ERC1155Test is Test { amounts[1] = amount2; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch( - owner, - ids, - amounts, - new bytes(id2 % 2) - ); + ERC1155Extended.safe_mint_batch(owner, ids, amounts, new bytes(id2 % 2)); assertEq(ERC1155Extended.total_supply(ids[0]), amounts[0]); assertEq(ERC1155Extended.total_supply(ids[1]), amounts[1]); vm.stopPrank(); } - function testFuzzTotalSupplyAfterSingleBurn( - address owner, - uint256 id, - bytes calldata data - ) public { - vm.assume( - owner != zeroAddress && - owner != makeAddr("secondOwner") && - owner.code.length == 0 && - id > 0 - ); + function testFuzzTotalSupplyAfterSingleBurn(address owner, uint256 id, bytes calldata data) public { + vm.assume(owner != zeroAddress && owner != makeAddr("secondOwner") && owner.code.length == 0 && id > 0); vm.startPrank(deployer); ERC1155Extended.safe_mint(owner, id, 15, data); ERC1155Extended.safe_mint(makeAddr("secondOwner"), id, 20, data); @@ -3001,13 +2452,7 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -3017,12 +2462,7 @@ contract ERC1155Test is Test { amounts[1] = amount2; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch( - owner, - ids, - amounts, - new bytes(id2 % 2) - ); + ERC1155Extended.safe_mint_batch(owner, ids, amounts, new bytes(id2 % 2)); vm.stopPrank(); vm.startPrank(owner); @@ -3032,17 +2472,10 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzBurnSuccess( - address firstOwner, - address secondOwner, - uint256 id - ) public { + function testFuzzBurnSuccess(address firstOwner, address secondOwner, uint256 id) public { vm.assume( - firstOwner != zeroAddress && - firstOwner.code.length == 0 && - firstOwner != secondOwner && - secondOwner != zeroAddress && - secondOwner.code.length == 0 + firstOwner != zeroAddress && firstOwner.code.length == 0 && firstOwner != secondOwner + && secondOwner != zeroAddress && secondOwner.code.length == 0 ); uint256 burnAmount = 10; bytes memory data = new bytes(0); @@ -3053,13 +2486,7 @@ contract ERC1155Test is Test { vm.startPrank(firstOwner); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - firstOwner, - firstOwner, - zeroAddress, - id, - burnAmount - ); + emit IERC1155.TransferSingle(firstOwner, firstOwner, zeroAddress, id, burnAmount); ERC1155Extended.burn(firstOwner, id, 10); assertEq(ERC1155Extended.total_supply(id), 25); assertEq(ERC1155Extended.balanceOf(firstOwner, id), 5); @@ -3067,20 +2494,10 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzBurnBatchSuccess( - address owner, - uint256 id1, - uint256 amount1, - uint256 id2, - uint256 amount2 - ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); + function testFuzzBurnBatchSuccess(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) + public + { + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); bytes memory data = new bytes(id2 % 2); @@ -3115,32 +2532,17 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && - owner != receiver && - owner.code.length == 0 && - receiver != zeroAddress && - receiver.code.length == 0 + owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress + && receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id1, - amount1 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id2, - amount2 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -3149,53 +2551,21 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeMintNoData( - address owner, - uint256 id1, - uint256 amount1, - uint256 id2, - uint256 amount2 - ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + function testFuzzSafeMintNoData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) public { + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id1, - amount1 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id2, - amount2 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -3212,45 +2582,19 @@ contract ERC1155Test is Test { uint256 amount2, bytes calldata data ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id1, - amount1 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle( - deployer, - zeroAddress, - receiver, - id2, - amount2 - ); + emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -3286,11 +2630,8 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && - owner != receiver && - owner.code.length == 0 && - receiver != zeroAddress && - receiver.code.length == 0 + owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress + && receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); uint256[] memory ids = new uint256[](2); @@ -3303,13 +2644,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -3318,32 +2653,14 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeMintBatchNoData( - address owner, - uint256 id1, - uint256 amount1, - uint256 id2, - uint256 amount2 - ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + function testFuzzSafeMintBatchNoData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) + public + { + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -3356,13 +2673,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -3371,32 +2682,14 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeMintBatchWithData( - address owner, - uint256 id1, - uint256 amount1, - uint256 id2, - uint256 amount2 - ) public { - vm.assume( - owner != zeroAddress && - owner.code.length == 0 && - id1 != id2 && - amount1 > 0 && - amount2 > 0 - ); - bytes4 receiverSingleMagicValue = IERC1155Receiver - .onERC1155Received - .selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver - .onERC1155BatchReceived - .selector; - ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( - receiverSingleMagicValue, - false, - receiverBatchMagicValue, - false - ); + function testFuzzSafeMintBatchWithData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) + public + { + vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; + ERC1155ReceiverMock erc1155ReceiverMock = + new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -3413,13 +2706,7 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch( - deployer, - zeroAddress, - receiver, - ids, - amounts - ); + emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -3465,24 +2752,15 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSetMinterNonOwner( - address msgSender, - string calldata minter - ) public { + function testFuzzSetMinterNonOwner(address msgSender, string calldata minter) public { vm.assume(msgSender != deployer); vm.expectRevert(bytes("Ownable: caller is not the owner")); ERC1155Extended.set_minter(makeAddr(minter), true); } - function testFuzzTransferOwnershipSuccess( - address newOwner1, - address newOwner2 - ) public { + function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { vm.assume( - newOwner1 != zeroAddress && - newOwner1 != deployer && - newOwner1 != newOwner2 && - newOwner2 != zeroAddress + newOwner1 != zeroAddress && newOwner1 != deployer && newOwner1 != newOwner2 && newOwner2 != zeroAddress ); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -3513,10 +2791,7 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner( - address nonOwner, - address newOwner - ) public { + function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -3568,9 +2843,7 @@ contract ERC1155Invariants is Test { function setUp() public { bytes memory args = abi.encode(_BASE_URI); - ERC1155Extended = IERC1155Extended( - vyperDeployer.deployContract("src/tokens/", "ERC1155", args) - ); + ERC1155Extended = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); erc1155Handler = new ERC1155Handler(ERC1155Extended, deployer); targetContract(address(erc1155Handler)); targetSender(deployer); @@ -3597,13 +2870,7 @@ contract ERC1155Handler { token.setApprovalForAll(operator, approved); } - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes calldata data - ) public { + function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) public { token.safeTransferFrom(from, to, id, amount, data); } @@ -3621,29 +2888,17 @@ contract ERC1155Handler { token.burn(ownerAddr, id, amount); } - function burn_batch( - address ownerAddr, - uint256[] calldata ids, - uint256[] calldata amounts - ) public { + function burn_batch(address ownerAddr, uint256[] calldata ids, uint256[] calldata amounts) public { token.burn_batch(ownerAddr, ids, amounts); } - function safe_mint( - address ownerAddr, - uint256 id, - uint256 amount, - bytes calldata data - ) public { + function safe_mint(address ownerAddr, uint256 id, uint256 amount, bytes calldata data) public { token.safe_mint(ownerAddr, id, amount, data); } - function safe_mint_batch( - address ownerAddr, - uint256[] calldata ids, - uint256[] calldata amounts, - bytes calldata data - ) public { + function safe_mint_batch(address ownerAddr, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) + public + { token.safe_mint_batch(ownerAddr, ids, amounts, data); } diff --git a/test/tokens/ERC20.t.sol b/test/tokens/ERC20.t.sol index 56e02b2d..0c229430 100644 --- a/test/tokens/ERC20.t.sol +++ b/test/tokens/ERC20.t.sol @@ -15,17 +15,9 @@ contract ERC20Test is Test { string private constant _VERSION_EIP712 = "1"; uint256 private constant _INITIAL_SUPPLY = type(uint8).max; bytes32 private constant _TYPE_HASH = - keccak256( - bytes( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ) - ); + keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256( - bytes( - "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" - ) - ); + keccak256(bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")); VyperDeployer private vyperDeployer = new VyperDeployer(); @@ -42,16 +34,8 @@ contract ERC20Test is Test { address private ERC20ExtendedAddr; function setUp() public { - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - _INITIAL_SUPPLY, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC20Extended = IERC20Extended( - vyperDeployer.deployContract("src/tokens/", "ERC20", args) - ); + bytes memory args = abi.encode(_NAME, _SYMBOL, _INITIAL_SUPPLY, _NAME_EIP712, _VERSION_EIP712); + ERC20Extended = IERC20Extended(vyperDeployer.deployContract("src/tokens/", "ERC20", args)); ERC20ExtendedAddr = address(ERC20Extended); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( @@ -70,10 +54,7 @@ contract ERC20Test is Test { assertEq(ERC20Extended.name(), _NAME); assertEq(ERC20Extended.symbol(), _SYMBOL); assertEq(ERC20Extended.totalSupply(), _INITIAL_SUPPLY * multiplier); - assertEq( - ERC20Extended.balanceOf(deployer), - _INITIAL_SUPPLY * multiplier - ); + assertEq(ERC20Extended.balanceOf(deployer), _INITIAL_SUPPLY * multiplier); assertEq(ERC20Extended.owner(), deployer); assertTrue(ERC20Extended.is_minter(deployer)); @@ -82,32 +63,14 @@ contract ERC20Test is Test { vm.expectEmit(true, false, false, true); emit IERC20Extended.RoleMinterChanged(deployer, true); vm.expectEmit(true, true, false, true); - emit IERC20.Transfer( - zeroAddress, - deployer, - _INITIAL_SUPPLY * multiplier - ); - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - _INITIAL_SUPPLY, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC20ExtendedInitialEvent = IERC20Extended( - vyperDeployer.deployContract("src/tokens/", "ERC20", args) - ); + emit IERC20.Transfer(zeroAddress, deployer, _INITIAL_SUPPLY * multiplier); + bytes memory args = abi.encode(_NAME, _SYMBOL, _INITIAL_SUPPLY, _NAME_EIP712, _VERSION_EIP712); + ERC20ExtendedInitialEvent = IERC20Extended(vyperDeployer.deployContract("src/tokens/", "ERC20", args)); assertEq(ERC20ExtendedInitialEvent.decimals(), 18); assertEq(ERC20ExtendedInitialEvent.name(), _NAME); assertEq(ERC20ExtendedInitialEvent.symbol(), _SYMBOL); - assertEq( - ERC20ExtendedInitialEvent.totalSupply(), - _INITIAL_SUPPLY * multiplier - ); - assertEq( - ERC20ExtendedInitialEvent.balanceOf(deployer), - _INITIAL_SUPPLY * multiplier - ); + assertEq(ERC20ExtendedInitialEvent.totalSupply(), _INITIAL_SUPPLY * multiplier); + assertEq(ERC20ExtendedInitialEvent.balanceOf(deployer), _INITIAL_SUPPLY * multiplier); assertEq(ERC20ExtendedInitialEvent.owner(), deployer); assertTrue(ERC20ExtendedInitialEvent.is_minter(deployer)); } @@ -119,10 +82,7 @@ contract ERC20Test is Test { function testBalanceOf() public { uint256 multiplier = 10 ** uint256(ERC20Extended.decimals()); - assertEq( - ERC20Extended.balanceOf(deployer), - _INITIAL_SUPPLY * multiplier - ); + assertEq(ERC20Extended.balanceOf(deployer), _INITIAL_SUPPLY * multiplier); assertEq(ERC20Extended.balanceOf(makeAddr("account")), 0); } @@ -268,11 +228,7 @@ contract ERC20Test is Test { ERC20Extended.approve(spender, amount); vm.startPrank(spender); vm.expectEmit(true, true, false, true); - emit IERC20.Approval( - owner, - spender, - ERC20Extended.allowance(owner, spender) - amount - ); + emit IERC20.Approval(owner, spender, ERC20Extended.allowance(owner, spender) - amount); vm.expectEmit(true, true, false, true); emit IERC20.Transfer(owner, to, amount); bool returnValue = ERC20Extended.transferFrom(owner, to, amount); @@ -405,11 +361,7 @@ contract ERC20Test is Test { ERC20Extended.approve(spender, amount); vm.startPrank(spender); vm.expectEmit(true, true, false, true); - emit IERC20.Approval( - owner, - spender, - ERC20Extended.allowance(owner, spender) - amount - ); + emit IERC20.Approval(owner, spender, ERC20Extended.allowance(owner, spender) - amount); vm.expectEmit(true, true, false, true); emit IERC20.Transfer(owner, zeroAddress, amount); @@ -430,11 +382,7 @@ contract ERC20Test is Test { ERC20Extended.approve(spender, balance); vm.startPrank(spender); vm.expectEmit(true, true, false, true); - emit IERC20.Approval( - owner, - spender, - ERC20Extended.allowance(owner, spender) - amount - ); + emit IERC20.Approval(owner, spender, ERC20Extended.allowance(owner, spender) - amount); vm.expectEmit(true, true, false, true); emit IERC20.Transfer(owner, zeroAddress, amount); @@ -513,10 +461,7 @@ contract ERC20Test is Test { emit IERC20.Transfer(zeroAddress, owner, amount); ERC20Extended.mint(owner, amount); assertEq(ERC20Extended.balanceOf(owner), amount); - assertEq( - ERC20Extended.totalSupply(), - (amount + _INITIAL_SUPPLY * multiplier) - ); + assertEq(ERC20Extended.totalSupply(), (amount + _INITIAL_SUPPLY * multiplier)); vm.stopPrank(); } @@ -584,16 +529,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); @@ -618,16 +554,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); @@ -652,16 +579,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); @@ -691,16 +609,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); @@ -722,16 +631,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); @@ -753,16 +653,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) ) ) ); @@ -807,13 +698,7 @@ contract ERC20Test is Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(ERC20Extended.DOMAIN_SEPARATOR(), digest); } @@ -882,17 +767,8 @@ contract ERC20Test is Test { assertEq(ERC20Extended.balanceOf(to), amount); } - function testFuzzTransferInvalidAmount( - address owner, - address to, - uint256 amount - ) public { - vm.assume( - owner != deployer && - owner != zeroAddress && - to != zeroAddress && - amount != 0 - ); + function testFuzzTransferInvalidAmount(address owner, address to, uint256 amount) public { + vm.assume(owner != deployer && owner != zeroAddress && to != zeroAddress && amount != 0); vm.prank(owner); vm.expectRevert(bytes("ERC20: transfer amount exceeds balance")); ERC20Extended.transfer(to, amount); @@ -908,19 +784,9 @@ contract ERC20Test is Test { assertEq(ERC20Extended.allowance(owner, spender), amount); } - function testFuzzTransferFromSuccess( - address owner, - address to, - uint256 amount - ) public { + function testFuzzTransferFromSuccess(address owner, address to, uint256 amount) public { address spender = self; - vm.assume( - to != zeroAddress && - owner != zeroAddress && - owner != to && - to != spender && - to != deployer - ); + vm.assume(to != zeroAddress && owner != zeroAddress && owner != to && to != spender && to != deployer); amount = bound(amount, 0, type(uint64).max); uint256 give = type(uint256).max; deal(ERC20ExtendedAddr, owner, give); @@ -939,12 +805,9 @@ contract ERC20Test is Test { assertEq(ERC20Extended.allowance(owner, spender), 0); } - function testFuzzTransferFromInsufficientAllowance( - address owner, - address to, - uint256 amount, - uint8 increment - ) public { + function testFuzzTransferFromInsufficientAllowance(address owner, address to, uint256 amount, uint8 increment) + public + { address spender = self; vm.assume(to != zeroAddress && owner != zeroAddress && increment != 0); amount = bound(amount, 0, type(uint64).max); @@ -999,11 +862,7 @@ contract ERC20Test is Test { assertEq(ERC20Extended.allowance(owner, spender), 0); } - function testFuzzBurnFromInsufficientAllowance( - address owner, - uint256 amount, - uint8 increment - ) public { + function testFuzzBurnFromInsufficientAllowance(address owner, uint256 amount, uint8 increment) public { vm.assume(owner != zeroAddress && owner != deployer && increment != 0); address spender = self; amount = bound(amount, 0, type(uint64).max); @@ -1027,17 +886,11 @@ contract ERC20Test is Test { emit IERC20.Transfer(zeroAddress, ownerAddr, amount); ERC20Extended.mint(ownerAddr, amount); assertEq(ERC20Extended.balanceOf(ownerAddr), amount); - assertEq( - ERC20Extended.totalSupply(), - (amount + _INITIAL_SUPPLY * multiplier) - ); + assertEq(ERC20Extended.totalSupply(), (amount + _INITIAL_SUPPLY * multiplier)); vm.stopPrank(); } - function testFuzzMintNonMinter( - string calldata owner, - uint256 amount - ) public { + function testFuzzMintNonMinter(string calldata owner, uint256 amount) public { vm.expectRevert(bytes("AccessControl: access is denied")); ERC20Extended.mint(makeAddr(owner), amount); } @@ -1058,20 +911,13 @@ contract ERC20Test is Test { vm.stopPrank(); } - function testFuzzSetMinterNonOwner( - address msgSender, - string calldata minter - ) public { + function testFuzzSetMinterNonOwner(address msgSender, string calldata minter) public { vm.assume(msgSender != deployer); vm.expectRevert(bytes("Ownable: caller is not the owner")); ERC20Extended.set_minter(makeAddr(minter), true); } - function testFuzzPermitSuccess( - string calldata owner, - string calldata spender, - uint16 increment - ) public { + function testFuzzPermitSuccess(string calldata owner, string calldata spender, uint16 increment) public { (address ownerAddr, uint256 key) = makeAddrAndKey(owner); address spenderAddr = makeAddr(spender); uint256 amount = block.number; @@ -1085,16 +931,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - ownerAddr, - spenderAddr, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) ) ) ); @@ -1105,15 +942,9 @@ contract ERC20Test is Test { assertEq(ERC20Extended.nonces(ownerAddr), 1); } - function testFuzzPermitInvalid( - string calldata owner, - string calldata spender, - uint16 increment - ) public { - vm.assume( - keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong")) - ); - (address ownerAddr, ) = makeAddrAndKey(owner); + function testFuzzPermitInvalid(string calldata owner, string calldata spender, uint16 increment) public { + vm.assume(keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong"))); + (address ownerAddr,) = makeAddrAndKey(owner); (, uint256 keyWrong) = makeAddrAndKey("ownerWrong"); address spenderAddr = makeAddr(spender); uint256 amount = block.number; @@ -1127,16 +958,7 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - ownerAddr, - spenderAddr, - amount, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) ) ) ); @@ -1164,11 +986,7 @@ contract ERC20Test is Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume( - randomHex != hex"0f" && - randomSalt != bytes32(0) && - randomExtensions.length != 0 - ); + vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -1185,32 +1003,17 @@ contract ERC20Test is Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, ERC20ExtendedAddr); assertTrue(salt != randomSalt); - assertTrue( - keccak256(abi.encode(extensions)) != - keccak256(abi.encode(randomExtensions)) - ); + assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(ERC20Extended.DOMAIN_SEPARATOR(), digest); } - function testFuzzTransferOwnershipSuccess( - address newOwner1, - address newOwner2 - ) public { + function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { vm.assume( - newOwner1 != zeroAddress && - newOwner1 != deployer && - newOwner1 != newOwner2 && - newOwner2 != zeroAddress + newOwner1 != zeroAddress && newOwner1 != deployer && newOwner1 != newOwner2 && newOwner2 != zeroAddress ); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -1241,10 +1044,7 @@ contract ERC20Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner( - address nonOwner, - address newOwner - ) public { + function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -1299,21 +1099,9 @@ contract ERC20Invariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - _INITIAL_SUPPLY, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC20Extended = IERC20Extended( - vyperDeployer.deployContract("src/tokens/", "ERC20", args) - ); - erc20Handler = new ERC20Handler( - ERC20Extended, - _INITIAL_SUPPLY, - deployer - ); + bytes memory args = abi.encode(_NAME, _SYMBOL, _INITIAL_SUPPLY, _NAME_EIP712, _VERSION_EIP712); + ERC20Extended = IERC20Extended(vyperDeployer.deployContract("src/tokens/", "ERC20", args)); + erc20Handler = new ERC20Handler(ERC20Extended, _INITIAL_SUPPLY, deployer); targetContract(address(erc20Handler)); targetSender(deployer); } @@ -1349,23 +1137,13 @@ contract ERC20Handler { token.approve(spender, amount); } - function transferFrom( - address ownerAddr, - address to, - uint256 amount - ) public { + function transferFrom(address ownerAddr, address to, uint256 amount) public { token.transferFrom(ownerAddr, to, amount); } - function permit( - address ownerAddr, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) public { + function permit(address ownerAddr, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) + public + { token.permit(ownerAddr, spender, value, deadline, v, r, s); } diff --git a/test/tokens/ERC721.t.sol b/test/tokens/ERC721.t.sol index b1e69816..755e482a 100644 --- a/test/tokens/ERC721.t.sol +++ b/test/tokens/ERC721.t.sol @@ -25,17 +25,9 @@ contract ERC721Test is Test { string private constant _NAME_EIP712 = "MyNFT"; string private constant _VERSION_EIP712 = "1"; bytes32 private constant _TYPE_HASH = - keccak256( - bytes( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ) - ); + keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256( - bytes( - "Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)" - ) - ); + keccak256(bytes("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)")); VyperDeployer private vyperDeployer = new VyperDeployer(); @@ -57,11 +49,7 @@ contract ERC721Test is Test { * @param tokenId The 32-byte identifier of the token. * @param receiver The 20-byte receiver address. */ - function _transferSuccess( - address owner, - uint256 tokenId, - address receiver - ) internal { + function _transferSuccess(address owner, uint256 tokenId, address receiver) internal { assertEq(ERC721Extended.ownerOf(tokenId), receiver); assertEq(ERC721Extended.getApproved(tokenId), zeroAddress); assertEq(ERC721Extended.balanceOf(owner), 1); @@ -95,24 +83,11 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: caller is not token owner or approved")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) ); } vm.stopPrank(); @@ -121,24 +96,11 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: transfer from incorrect owner")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - receiver, - receiver, - tokenId - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - receiver, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId, data) ); } vm.stopPrank(); @@ -147,24 +109,11 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: invalid token ID")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - receiver, - receiver, - tokenId + 2 - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId + 2) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - receiver, - receiver, - tokenId + 2, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId + 2, data) ); } vm.stopPrank(); @@ -173,24 +122,11 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: transfer to the zero address")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - zeroAddress, - tokenId - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, zeroAddress, tokenId) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - zeroAddress, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, zeroAddress, tokenId, data) ); } vm.stopPrank(); @@ -227,24 +163,11 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) ); } _transferSuccess(owner, tokenId, receiver); @@ -257,24 +180,11 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) ); } _transferSuccess(owner, tokenId, receiver); @@ -287,24 +197,11 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) ); } _transferSuccess(owner, tokenId, receiver); @@ -320,24 +217,11 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) ); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) ); } _transferSuccess(owner, tokenId, receiver); @@ -349,20 +233,10 @@ contract ERC721Test is Test { vm.expectEmit(true, true, true, false); emit IERC721.Transfer(owner, owner, tokenId); if (!withData) { - Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature(transferFunction, owner, owner, tokenId) - ); + Address.functionCall(ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, owner, tokenId)); } else { Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - owner, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, owner, tokenId, data) ); } assertEq(ERC721Extended.ownerOf(tokenId), owner); @@ -376,14 +250,7 @@ contract ERC721Test is Test { /** * @dev Validates all possible reverts. */ - _transferReverts( - transferFunction, - owner, - tokenId, - receiver, - withData, - data - ); + _transferReverts(transferFunction, owner, tokenId, receiver, withData, data); } /** @@ -410,28 +277,12 @@ contract ERC721Test is Test { ) internal { uint256 snapshot = vm.snapshot(); _shouldTransferTokensByUsers( - transferFunction, - owner, - approved, - operator, - tokenId, - makeAddr("receiver"), - true, - data + transferFunction, owner, approved, operator, tokenId, makeAddr("receiver"), true, data ); vm.revertTo(snapshot); snapshot = vm.snapshot(); - _shouldTransferTokensByUsers( - transferFunction, - owner, - approved, - operator, - tokenId, - receiver, - true, - data - ); + _shouldTransferTokensByUsers(transferFunction, owner, approved, operator, tokenId, receiver, true, data); vm.revertTo(snapshot); snapshot = vm.snapshot(); @@ -439,14 +290,7 @@ contract ERC721Test is Test { vm.expectEmit(true, true, true, true, receiver); emit ERC721ReceiverMock.Received(owner, owner, tokenId, data); Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) ); _transferSuccess(owner, tokenId, receiver); vm.stopPrank(); @@ -457,14 +301,7 @@ contract ERC721Test is Test { vm.expectEmit(true, true, true, true, receiver); emit ERC721ReceiverMock.Received(approved, owner, tokenId, data); Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) ); _transferSuccess(owner, tokenId, receiver); vm.stopPrank(); @@ -473,29 +310,14 @@ contract ERC721Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC721: invalid token ID")); Address.functionCall( - ERC721ExtendedAddr, - abi.encodeWithSignature( - transferFunction, - owner, - receiver, - tokenId + 2, - data - ) + ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId + 2, data) ); vm.stopPrank(); } function setUp() public { - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - _BASE_URI, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC721Extended = IERC721Extended( - vyperDeployer.deployContract("src/tokens/", "ERC721", args) - ); + bytes memory args = abi.encode(_NAME, _SYMBOL, _BASE_URI, _NAME_EIP712, _VERSION_EIP712); + ERC721Extended = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); ERC721ExtendedAddr = address(ERC721Extended); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( @@ -519,16 +341,8 @@ contract ERC721Test is Test { emit IERC721Extended.OwnershipTransferred(zeroAddress, deployer); vm.expectEmit(true, false, false, true); emit IERC721Extended.RoleMinterChanged(deployer, true); - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - _BASE_URI, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC721ExtendedInitialEvent = IERC721Extended( - vyperDeployer.deployContract("src/tokens/", "ERC721", args) - ); + bytes memory args = abi.encode(_NAME, _SYMBOL, _BASE_URI, _NAME_EIP712, _VERSION_EIP712); + ERC721ExtendedInitialEvent = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); assertEq(ERC721ExtendedInitialEvent.name(), _NAME); assertEq(ERC721ExtendedInitialEvent.symbol(), _SYMBOL); assertEq(ERC721ExtendedInitialEvent.totalSupply(), 0); @@ -539,17 +353,9 @@ contract ERC721Test is Test { function testSupportsInterfaceSuccess() public { assertTrue(ERC721Extended.supportsInterface(type(IERC165).interfaceId)); assertTrue(ERC721Extended.supportsInterface(type(IERC721).interfaceId)); - assertTrue( - ERC721Extended.supportsInterface(type(IERC721Metadata).interfaceId) - ); - assertTrue( - ERC721Extended.supportsInterface( - type(IERC721Enumerable).interfaceId - ) - ); - assertTrue( - ERC721Extended.supportsInterface(type(IERC4494).interfaceId) - ); + assertTrue(ERC721Extended.supportsInterface(type(IERC721Metadata).interfaceId)); + assertTrue(ERC721Extended.supportsInterface(type(IERC721Enumerable).interfaceId)); + assertTrue(ERC721Extended.supportsInterface(type(IERC4494).interfaceId)); assertTrue(ERC721Extended.supportsInterface(0x49064906)); } @@ -557,10 +363,7 @@ contract ERC721Test is Test { uint256 startGas = gasleft(); ERC721Extended.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && - ERC721Extended.supportsInterface(type(IERC165).interfaceId) - ); + assertTrue(gasUsed <= 30_000 && ERC721Extended.supportsInterface(type(IERC165).interfaceId)); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -571,9 +374,7 @@ contract ERC721Test is Test { uint256 startGas = gasleft(); ERC721Extended.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && !ERC721Extended.supportsInterface(0x0011bbff) - ); + assertTrue(gasUsed <= 30_000 && !ERC721Extended.supportsInterface(0x0011bbff)); } function testBalanceOfCase1() public { @@ -645,10 +446,8 @@ contract ERC721Test is Test { string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.None - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri1); @@ -672,13 +471,7 @@ contract ERC721Test is Test { ); _shouldTransferSafely( - "safeTransferFrom(address,address,uint256,bytes)", - owner, - approved, - operator, - 0, - receiver, - new bytes(0) + "safeTransferFrom(address,address,uint256,bytes)", owner, approved, operator, 0, receiver, new bytes(0) ); } @@ -689,10 +482,8 @@ contract ERC721Test is Test { string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.None - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri1); @@ -705,32 +496,21 @@ contract ERC721Test is Test { vm.stopPrank(); _shouldTransferSafely( - "safeTransferFrom(address,address,uint256,bytes)", - owner, - approved, - operator, - 0, - receiver, - new bytes(42) + "safeTransferFrom(address,address,uint256,bytes)", owner, approved, operator, 0, receiver, new bytes(42) ); } function testSafeTransferFromReceiverInvalidReturnIdentifier() public { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - 0x00bb8833, - ERC721ReceiverMock.Error.None - ); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock(0x00bb8833, ERC721ReceiverMock.Error.None); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert( - bytes("ERC721: transfer to non-ERC721Receiver implementer") - ); + vm.expectRevert(bytes("ERC721: transfer to non-ERC721Receiver implementer")); ERC721Extended.safeTransferFrom(owner, receiver, 0, new bytes(0)); vm.stopPrank(); } @@ -739,10 +519,8 @@ contract ERC721Test is Test { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.RevertWithMessage - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithMessage); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); @@ -758,10 +536,8 @@ contract ERC721Test is Test { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.RevertWithoutMessage - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithoutMessage); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); @@ -777,10 +553,8 @@ contract ERC721Test is Test { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.Panic - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.Panic); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); @@ -953,11 +727,7 @@ contract ERC721Test is Test { vm.stopPrank(); vm.startPrank(makeAddr("nonOwner")); - vm.expectRevert( - bytes( - "ERC721: approve caller is not token owner or approved for all" - ) - ); + vm.expectRevert(bytes("ERC721: approve caller is not token owner or approved for all")); ERC721Extended.approve(makeAddr("to"), tokenId); vm.stopPrank(); } @@ -976,11 +746,7 @@ contract ERC721Test is Test { vm.stopPrank(); vm.startPrank(spender); - vm.expectRevert( - bytes( - "ERC721: approve caller is not token owner or approved for all" - ) - ); + vm.expectRevert(bytes("ERC721: approve caller is not token owner or approved for all")); ERC721Extended.approve(makeAddr("to"), tokenId); vm.stopPrank(); } @@ -1146,16 +912,8 @@ contract ERC721Test is Test { } function testTokenURINoBaseURI() public { - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - "", - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC721ExtendedNoBaseURI = IERC721Extended( - vyperDeployer.deployContract("src/tokens/", "ERC721", args) - ); + bytes memory args = abi.encode(_NAME, _SYMBOL, "", _NAME_EIP712, _VERSION_EIP712); + ERC721ExtendedNoBaseURI = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1260,44 +1018,23 @@ contract ERC721Test is Test { ERC721Extended.burn(0); vm.stopPrank(); assertEq(ERC721Extended.totalSupply(), 2); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), - tokenId + 2 - ); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), - tokenId + 1 - ); + assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), tokenId + 2); + assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), tokenId + 1); vm.startPrank(owner); ERC721Extended.safeTransferFrom(owner, other, tokenId + 1, ""); vm.stopPrank(); assertEq(ERC721Extended.totalSupply(), 2); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), - tokenId + 2 - ); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(other, tokenId), - tokenId + 1 - ); + assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), tokenId + 2); + assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId), tokenId + 1); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, ""); vm.stopPrank(); assertEq(ERC721Extended.totalSupply(), 3); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), - tokenId + 2 - ); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), - tokenId + 3 - ); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(other, tokenId), - tokenId + 1 - ); + assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), tokenId + 2); + assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), tokenId + 3); + assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId), tokenId + 1); } function testTokenOfOwnerByIndexReverts() public { @@ -1325,14 +1062,8 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721Enumerable: owner index out of bounds")); ERC721Extended.tokenOfOwnerByIndex(owner, tokenId); assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId), tokenId); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 1), - tokenId + 1 - ); - assertEq( - ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 2), - tokenId + 2 - ); + assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 1), tokenId + 1); + assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 2), tokenId + 2); } function testBurnSuccess() public { @@ -1468,11 +1199,7 @@ contract ERC721Test is Test { * @dev To display the default storage layout for a contract * in Vyper, use `vyper -f layout yourFileName.vy`. */ - vm.store( - ERC721ExtendedAddr, - bytes32(uint256(18_446_744_073_709_551_627)), - bytes32(0) - ); + vm.store(ERC721ExtendedAddr, bytes32(uint256(18_446_744_073_709_551_627)), bytes32(0)); vm.expectRevert(bytes("ERC721: token already minted")); ERC721Extended.safe_mint(owner, ""); vm.stopPrank(); @@ -1480,10 +1207,8 @@ contract ERC721Test is Test { function testSafeMintReceiverContract() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.None - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -1496,26 +1221,19 @@ contract ERC721Test is Test { } function testSafeMintReceiverContractInvalidReturnIdentifier() public { - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - 0x00bb8833, - ERC721ReceiverMock.Error.None - ); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock(0x00bb8833, ERC721ReceiverMock.Error.None); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); - vm.expectRevert( - bytes("ERC721: transfer to non-ERC721Receiver implementer") - ); + vm.expectRevert(bytes("ERC721: transfer to non-ERC721Receiver implementer")); ERC721Extended.safe_mint(owner, uri); vm.stopPrank(); } function testSafeMintReceiverContractRevertsWithMessage() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.RevertWithMessage - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithMessage); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1526,10 +1244,8 @@ contract ERC721Test is Test { function testSafeMintReceiverContractRevertsWithoutMessage() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.RevertWithoutMessage - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithoutMessage); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1540,10 +1256,8 @@ contract ERC721Test is Test { function testSafeMintReceiverContractRevertsWithPanic() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.Panic - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.Panic); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1576,11 +1290,7 @@ contract ERC721Test is Test { * @dev To display the default storage layout for a contract * in Vyper, use `vyper -f layout yourFileName.vy`. */ - vm.store( - ERC721ExtendedAddr, - bytes32(uint256(18_446_744_073_709_551_627)), - bytes32(type(uint256).max) - ); + vm.store(ERC721ExtendedAddr, bytes32(uint256(18_446_744_073_709_551_627)), bytes32(type(uint256).max)); vm.prank(deployer); vm.expectRevert(); ERC721Extended.safe_mint(makeAddr("owner"), "my_awesome_nft_uri"); @@ -1638,15 +1348,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spender, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) ) ) ); @@ -1676,15 +1378,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spender, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) ) ) ); @@ -1714,15 +1408,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spender, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) ) ) ); @@ -1757,15 +1443,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spender, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) ) ) ); @@ -1792,15 +1470,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spender, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) ) ) ); @@ -1827,15 +1497,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spender, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) ) ) ); @@ -1880,13 +1542,7 @@ contract ERC721Test is Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(ERC721Extended.DOMAIN_SEPARATOR(), digest); } @@ -1942,22 +1598,11 @@ contract ERC721Test is Test { ERC721Extended.renounce_ownership(); } - function testFuzzTransferFrom( - address owner, - address approved, - address operator - ) public { + function testFuzzTransferFrom(address owner, address approved, address operator) public { + vm.assume(owner > address(4_096) && approved > address(4_096) && operator > address(4_096)); vm.assume( - owner > address(4_096) && - approved > address(4_096) && - operator > address(4_096) - ); - vm.assume( - owner != approved && - owner != operator && - owner != zeroAddress && - owner.code.length == 0 && - owner != makeAddr("receiver") + owner != approved && owner != operator && owner != zeroAddress && owner.code.length == 0 + && owner != makeAddr("receiver") ); string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; @@ -1983,31 +1628,19 @@ contract ERC721Test is Test { ); } - function testFuzzSafeTransferFromWithData( - address owner, - address approved, - address operator, - bytes memory data - ) public { + function testFuzzSafeTransferFromWithData(address owner, address approved, address operator, bytes memory data) + public + { + vm.assume(owner > address(4_096) && approved > address(4_096) && operator > address(4_096)); vm.assume( - owner > address(4_096) && - approved > address(4_096) && - operator > address(4_096) - ); - vm.assume( - owner != approved && - owner != operator && - owner != zeroAddress && - owner.code.length == 0 && - owner != makeAddr("receiver") + owner != approved && owner != operator && owner != zeroAddress && owner.code.length == 0 + && owner != makeAddr("receiver") ); string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( - receiverMagicValue, - ERC721ReceiverMock.Error.None - ); + ERC721ReceiverMock erc721ReceiverMock = + new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); address receiver = address(erc721ReceiverMock); vm.assume(owner != receiver); vm.startPrank(deployer); @@ -2032,23 +1665,12 @@ contract ERC721Test is Test { ); _shouldTransferSafely( - "safeTransferFrom(address,address,uint256,bytes)", - owner, - approved, - operator, - 0, - receiver, - data + "safeTransferFrom(address,address,uint256,bytes)", owner, approved, operator, 0, receiver, data ); } - function testFuzzApproveClearingApprovalWithNoPriorApproval( - address owner, - address spender - ) public { - vm.assume( - owner != spender && owner != zeroAddress && owner.code.length == 0 - ); + function testFuzzApproveClearingApprovalWithNoPriorApproval(address owner, address spender) public { + vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -2064,13 +1686,8 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzApproveClearingApprovalWithPriorApproval( - address owner, - address spender1 - ) public { - vm.assume( - owner != spender1 && owner != zeroAddress && owner.code.length == 0 - ); + function testFuzzApproveClearingApprovalWithPriorApproval(address owner, address spender1) public { + vm.assume(owner != spender1 && owner != zeroAddress && owner.code.length == 0); vm.assume(spender1 > address(4_096)); address spender2 = zeroAddress; string memory uri = "my_awesome_nft_uri"; @@ -2092,13 +1709,8 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzApproveWithNoPriorApproval( - address owner, - address spender - ) public { - vm.assume( - owner != spender && owner != zeroAddress && owner.code.length == 0 - ); + function testFuzzApproveWithNoPriorApproval(address owner, address spender) public { + vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -2114,13 +1726,8 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzApproveWithPriorApproval( - address owner, - address spender - ) public { - vm.assume( - owner != spender && owner != zeroAddress && owner.code.length == 0 - ); + function testFuzzApproveWithPriorApproval(address owner, address spender) public { + vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -2152,31 +1759,14 @@ contract ERC721Test is Test { vm.stopPrank(); vm.startPrank(nonOwner); - vm.expectRevert( - bytes( - "ERC721: approve caller is not token owner or approved for all" - ) - ); + vm.expectRevert(bytes("ERC721: approve caller is not token owner or approved for all")); ERC721Extended.approve(makeAddr("to"), tokenId); vm.stopPrank(); } - function testFuzzApproveFromOperatorAddress( - address owner, - address operator, - address spender - ) public { - vm.assume( - owner > address(4_096) && - operator > address(4_096) && - spender > address(4_096) - ); - vm.assume( - owner != operator && - owner != spender && - owner != zeroAddress && - owner.code.length == 0 - ); + function testFuzzApproveFromOperatorAddress(address owner, address operator, address spender) public { + vm.assume(owner > address(4_096) && operator > address(4_096) && spender > address(4_096)); + vm.assume(owner != operator && owner != spender && owner != zeroAddress && owner.code.length == 0); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; vm.startPrank(deployer); @@ -2195,14 +1785,9 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzSetApprovalForAllSuccess( - address owner, - address operator - ) public { + function testFuzzSetApprovalForAllSuccess(address owner, address operator) public { vm.assume(owner > address(4_096) && operator > address(4_096)); - vm.assume( - owner != operator && owner != zeroAddress && owner.code.length == 0 - ); + vm.assume(owner != operator && owner != zeroAddress && owner.code.length == 0); bool approved = true; string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -2227,13 +1812,8 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzGetApprovedApprovedTokenId( - address owner, - address spender - ) public { - vm.assume( - owner != spender && owner != zeroAddress && owner.code.length == 0 - ); + function testFuzzGetApprovedApprovedTokenId(address owner, address spender) public { + vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -2330,20 +1910,13 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzSetMinterNonOwner( - address msgSender, - string calldata minter - ) public { + function testFuzzSetMinterNonOwner(address msgSender, string calldata minter) public { vm.assume(msgSender != deployer); vm.expectRevert(bytes("Ownable: caller is not the owner")); ERC721Extended.set_minter(makeAddr(minter), true); } - function testFuzzPermitSuccess( - string calldata owner, - string calldata spender, - uint16 increment - ) public { + function testFuzzPermitSuccess(string calldata owner, string calldata spender, uint16 increment) public { (address ownerAddr, uint256 key) = makeAddrAndKey(owner); address spenderAddr = makeAddr(spender); uint256 tokenId = 0; @@ -2362,15 +1935,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spenderAddr, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spenderAddr, tokenId, nonce, deadline)) ) ) ); @@ -2381,15 +1946,9 @@ contract ERC721Test is Test { assertEq(ERC721Extended.nonces(tokenId), 1); } - function testFuzzPermitInvalid( - string calldata owner, - string calldata spender, - uint16 increment - ) public { - vm.assume( - keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong")) - ); - (address ownerAddr, ) = makeAddrAndKey(owner); + function testFuzzPermitInvalid(string calldata owner, string calldata spender, uint16 increment) public { + vm.assume(keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong"))); + (address ownerAddr,) = makeAddrAndKey(owner); (, uint256 keyWrong) = makeAddrAndKey("ownerWrong"); address spenderAddr = makeAddr(spender); uint256 tokenId = 0; @@ -2408,15 +1967,7 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - spenderAddr, - tokenId, - nonce, - deadline - ) - ) + keccak256(abi.encode(_PERMIT_TYPE_HASH, spenderAddr, tokenId, nonce, deadline)) ) ) ); @@ -2444,11 +1995,7 @@ contract ERC721Test is Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume( - randomHex != hex"0f" && - randomSalt != bytes32(0) && - randomExtensions.length != 0 - ); + vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -2465,32 +2012,17 @@ contract ERC721Test is Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, ERC721ExtendedAddr); assertTrue(salt != randomSalt); - assertTrue( - keccak256(abi.encode(extensions)) != - keccak256(abi.encode(randomExtensions)) - ); + assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(ERC721Extended.DOMAIN_SEPARATOR(), digest); } - function testFuzzTransferOwnershipSuccess( - address newOwner1, - address newOwner2 - ) public { + function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { vm.assume( - newOwner1 != zeroAddress && - newOwner1 != deployer && - newOwner1 != newOwner2 && - newOwner2 != zeroAddress + newOwner1 != zeroAddress && newOwner1 != deployer && newOwner1 != newOwner2 && newOwner2 != zeroAddress ); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -2521,10 +2053,7 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner( - address nonOwner, - address newOwner - ) public { + function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -2579,16 +2108,8 @@ contract ERC721Invariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - bytes memory args = abi.encode( - _NAME, - _SYMBOL, - _BASE_URI, - _NAME_EIP712, - _VERSION_EIP712 - ); - ERC721Extended = IERC721Extended( - vyperDeployer.deployContract("src/tokens/", "ERC721", args) - ); + bytes memory args = abi.encode(_NAME, _SYMBOL, _BASE_URI, _NAME_EIP712, _VERSION_EIP712); + ERC721Extended = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); erc721Handler = new ERC721Handler(ERC721Extended, deployer); targetContract(address(erc721Handler)); targetSender(deployer); @@ -2617,11 +2138,7 @@ contract ERC721Handler { owner = owner_; } - function safeTransferFrom( - address ownerAddr, - address to, - bytes calldata data - ) public { + function safeTransferFrom(address ownerAddr, address to, bytes calldata data) public { token.safeTransferFrom(ownerAddr, to, counter, data); } @@ -2641,13 +2158,7 @@ contract ERC721Handler { token.setApprovalForAll(operator, approved); } - function permit( - address spender, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) public { + function permit(address spender, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { token.permit(spender, counter, deadline, v, r, s); } diff --git a/test/tokens/interfaces/IERC1155Extended.sol b/test/tokens/interfaces/IERC1155Extended.sol index bf87c467..e6539bf2 100644 --- a/test/tokens/interfaces/IERC1155Extended.sol +++ b/test/tokens/interfaces/IERC1155Extended.sol @@ -4,10 +4,7 @@ pragma solidity ^0.8.23; import {IERC1155MetadataURI} from "openzeppelin/token/ERC1155/extensions/IERC1155MetadataURI.sol"; interface IERC1155Extended is IERC1155MetadataURI { - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event RoleMinterChanged(address indexed minter, bool status); @@ -19,27 +16,14 @@ interface IERC1155Extended is IERC1155MetadataURI { function burn(address owner, uint256 id, uint256 amount) external; - function burn_batch( - address owner, - uint256[] calldata ids, - uint256[] calldata amounts - ) external; + function burn_batch(address owner, uint256[] calldata ids, uint256[] calldata amounts) external; function is_minter(address account) external view returns (bool); - function safe_mint( - address owner, - uint256 id, - uint256 amount, - bytes calldata data - ) external; - - function safe_mint_batch( - address owner, - uint256[] calldata ids, - uint256[] calldata amounts, - bytes calldata data - ) external; + function safe_mint(address owner, uint256 id, uint256 amount, bytes calldata data) external; + + function safe_mint_batch(address owner, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) + external; function set_minter(address minter, bool status) external; diff --git a/test/tokens/interfaces/IERC20Extended.sol b/test/tokens/interfaces/IERC20Extended.sol index f678cdb1..c47f5194 100644 --- a/test/tokens/interfaces/IERC20Extended.sol +++ b/test/tokens/interfaces/IERC20Extended.sol @@ -6,10 +6,7 @@ import {IERC20Permit} from "openzeppelin/token/ERC20/extensions/IERC20Permit.sol import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; interface IERC20Extended is IERC20Metadata, IERC20Permit, IERC5267 { - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event RoleMinterChanged(address indexed minter, bool status); diff --git a/test/tokens/interfaces/IERC4494.sol b/test/tokens/interfaces/IERC4494.sol index 2d99b238..5aaac6f1 100644 --- a/test/tokens/interfaces/IERC4494.sol +++ b/test/tokens/interfaces/IERC4494.sol @@ -4,14 +4,7 @@ pragma solidity ^0.8.23; import {IERC165} from "openzeppelin/utils/introspection/IERC165.sol"; interface IERC4494 is IERC165 { - function permit( - address spender, - uint256 tokenId, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; + function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; function nonces(uint256 tokenId) external view returns (uint256); diff --git a/test/tokens/interfaces/IERC721Extended.sol b/test/tokens/interfaces/IERC721Extended.sol index b3d737b0..ce0c27dd 100644 --- a/test/tokens/interfaces/IERC721Extended.sol +++ b/test/tokens/interfaces/IERC721Extended.sol @@ -7,17 +7,8 @@ import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; import {IERC4906} from "openzeppelin/interfaces/IERC4906.sol"; import {IERC4494} from "./IERC4494.sol"; -interface IERC721Extended is - IERC721Metadata, - IERC721Enumerable, - IERC4494, - IERC5267, - IERC4906 -{ - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); +interface IERC721Extended is IERC721Metadata, IERC721Enumerable, IERC4494, IERC5267, IERC4906 { + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event RoleMinterChanged(address indexed minter, bool status); diff --git a/test/tokens/mocks/ERC1155ReceiverMock.sol b/test/tokens/mocks/ERC1155ReceiverMock.sol index 9185f95f..0be565f6 100644 --- a/test/tokens/mocks/ERC1155ReceiverMock.sol +++ b/test/tokens/mocks/ERC1155ReceiverMock.sol @@ -18,28 +18,11 @@ contract ERC1155ReceiverMock is ERC165, IERC1155Receiver { bytes4 private batRetval; bool private batReverts; - event Received( - address indexed operator, - address indexed from, - uint256 id, - uint256 amount, - bytes data - ); + event Received(address indexed operator, address indexed from, uint256 id, uint256 amount, bytes data); - event BatchReceived( - address indexed operator, - address indexed from, - uint256[] ids, - uint256[] amounts, - bytes data - ); + event BatchReceived(address indexed operator, address indexed from, uint256[] ids, uint256[] amounts, bytes data); - constructor( - bytes4 recRetval_, - bool recReverts_, - bytes4 batRetval_, - bool batReverts_ - ) { + constructor(bytes4 recRetval_, bool recReverts_, bytes4 batRetval_, bool batReverts_) { recRetval = recRetval_; recReverts = recReverts_; batRetval = batRetval_; @@ -59,13 +42,10 @@ contract ERC1155ReceiverMock is ERC165, IERC1155Receiver { * to this smart contract. * @return bytes4 The 4-byte return identifier. */ - function onERC1155Received( - address operator, - address from, - uint256 id, - uint256 amount, - bytes memory data - ) external returns (bytes4) { + function onERC1155Received(address operator, address from, uint256 id, uint256 amount, bytes memory data) + external + returns (bytes4) + { // solhint-disable-next-line reason-string, custom-errors require(!recReverts, "ERC1155ReceiverMock: reverting on receive"); emit Received(operator, from, id, amount, data); diff --git a/test/tokens/mocks/ERC721ReceiverMock.sol b/test/tokens/mocks/ERC721ReceiverMock.sol index 03b46c89..ee63dd58 100644 --- a/test/tokens/mocks/ERC721ReceiverMock.sol +++ b/test/tokens/mocks/ERC721ReceiverMock.sol @@ -21,6 +21,7 @@ contract ERC721ReceiverMock is IERC721Receiver { Panic } // solhint-disable-next-line var-name-mixedcase + Error private immutable _ERROR; event Received(address operator, address from, uint256 tokenId, bytes data); @@ -40,12 +41,11 @@ contract ERC721ReceiverMock is IERC721Receiver { * to this smart contract. * @return bytes4 The 4-byte return identifier. */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public override returns (bytes4) { + function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) + public + override + returns (bytes4) + { if (_ERROR == Error.RevertWithMessage) { // solhint-disable-next-line custom-errors revert("ERC721ReceiverMock: reverting"); diff --git a/test/utils/Base64.t.sol b/test/utils/Base64.t.sol index 6a35ebf4..14d125bc 100644 --- a/test/utils/Base64.t.sol +++ b/test/utils/Base64.t.sol @@ -137,14 +137,8 @@ contract Base64Test is PRBTest { * @dev We remove the one trailing zero byte that stems from * the padding to ensure byte-level equality. */ - assertEq( - string(returnDataStd.slice(0, returnDataStd.length - 1)), - text - ); - assertEq( - string(returnDataUrl.slice(0, returnDataUrl.length - 1)), - text - ); + assertEq(string(returnDataStd.slice(0, returnDataStd.length - 1)), text); + assertEq(string(returnDataUrl.slice(0, returnDataUrl.length - 1)), text); } function testDecodeWithDoublePadding() public { @@ -158,14 +152,8 @@ contract Base64Test is PRBTest { * @dev We remove the two trailing zero bytes that stem from * the padding to ensure byte-level equality. */ - assertEq( - string(returnDataStd.slice(0, returnDataStd.length - 2)), - text - ); - assertEq( - string(returnDataUrl.slice(0, returnDataUrl.length - 2)), - text - ); + assertEq(string(returnDataStd.slice(0, returnDataStd.length - 2)), text); + assertEq(string(returnDataUrl.slice(0, returnDataUrl.length - 2)), text); } function testDecodeSingleCharacter() public { @@ -212,14 +200,8 @@ contract Base64Test is PRBTest { * @dev We remove the two trailing zero bytes that stem from * the padding to ensure byte-level equality. */ - assertEq( - string(returnDataStd.slice(0, returnDataStd.length - 2)), - text - ); - assertEq( - string(returnDataUrl.slice(0, returnDataUrl.length - 2)), - text - ); + assertEq(string(returnDataStd.slice(0, returnDataStd.length - 2)), text); + assertEq(string(returnDataUrl.slice(0, returnDataUrl.length - 2)), text); } function testDecodeSafeUrl() public { @@ -228,11 +210,7 @@ contract Base64Test is PRBTest { vm.expectRevert(bytes("Base64: invalid string")); base64.decode(data, false); bytes[] memory outputUrl = base64.decode(data, true); - bytes memory returnDataUrl = bytes.concat( - outputUrl[0], - outputUrl[1], - outputUrl[2] - ); + bytes memory returnDataUrl = bytes.concat(outputUrl[0], outputUrl[1], outputUrl[2]); assertEq(string(returnDataUrl), text); } diff --git a/test/utils/BatchDistributor.t.sol b/test/utils/BatchDistributor.t.sol index 18c9b11b..e97f49b5 100644 --- a/test/utils/BatchDistributor.t.sol +++ b/test/utils/BatchDistributor.t.sol @@ -19,23 +19,15 @@ contract BatchDistributorTest is Test { address private batchDistributorAddr; function setUp() public { - batchDistributor = IBatchDistributor( - vyperDeployer.deployContract("src/utils/", "BatchDistributor") - ); + batchDistributor = IBatchDistributor(vyperDeployer.deployContract("src/utils/", "BatchDistributor")); batchDistributorAddr = address(batchDistributor); } function testDistributeEtherOneAddressSuccess() public { address alice = makeAddr("alice"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](1); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 2 wei - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](1); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); batchDistributor.distribute_ether{value: 2 wei}(batch); assertEq(alice.balance, 2 wei); @@ -46,23 +38,11 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 2 wei - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 100 wei - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 2_000 wei - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); batchDistributor.distribute_ether{value: 2_102 wei}(batch); assertEq(alice.balance, 2 wei); @@ -78,59 +58,30 @@ contract BatchDistributorTest is Test { address msgSender = address(makeAddr("msgSender")); vm.deal(msgSender, 1 ether); uint256 balance = msgSender.balance; - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 2 wei - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 100 wei - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 2_000 wei - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); vm.prank(msgSender); batchDistributor.distribute_ether{value: 1 ether}(batch); assertEq(alice.balance, 2 wei); assertEq(bob.balance, 100 wei); assertEq(carol.balance, 2_000 wei); - assertEq( - msgSender.balance, - balance - alice.balance - bob.balance - carol.balance - ); + assertEq(msgSender.balance, balance - alice.balance - bob.balance - carol.balance); assertEq(batchDistributorAddr.balance, 0); } - function testDistributeEtherRevertWithNoFallbackFunctionForReceipt() - public - { + function testDistributeEtherRevertWithNoFallbackFunctionForReceipt() public { address alice = batchDistributorAddr; address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 2 wei - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 100 wei - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 2_000 wei - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); /** * @dev The `BatchDistributor` contract does not have a `fallback` function @@ -141,29 +92,15 @@ contract BatchDistributorTest is Test { assertEq(batchDistributorAddr.balance, 0); } - function testDistributeEtherRevertWithNoFallbackFunctionForMsgSender() - public - { + function testDistributeEtherRevertWithNoFallbackFunctionForMsgSender() public { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 2 wei - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 100 wei - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 2_000 wei - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); /** * @dev The `Test` contract does not have a `fallback` function and must @@ -178,23 +115,11 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 2 wei - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 100 wei - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 2_000 wei - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); /** * @dev Sends too little funds, which triggers an insufficient funds error. @@ -214,15 +139,9 @@ contract BatchDistributorTest is Test { erc20Mock.approve(batchDistributorAddr, 30); address alice = makeAddr("alice"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](1); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 30 - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](1); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 30}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); batchDistributor.distribute_token(erc20Mock, batch); vm.stopPrank(); @@ -242,23 +161,11 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 30 - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 20 - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 50 - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 30}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 20}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 50}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); batchDistributor.distribute_token(erc20Mock, batch); vm.stopPrank(); @@ -280,31 +187,14 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 30 - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 20 - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 50 - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 30}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 20}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 50}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); vm.expectRevert( - abi.encodeWithSelector( - IERC20Errors.ERC20InsufficientAllowance.selector, - batchDistributorAddr, - 99, - 100 - ) + abi.encodeWithSelector(IERC20Errors.ERC20InsufficientAllowance.selector, batchDistributorAddr, 99, 100) ); batchDistributor.distribute_token(erc20Mock, batch); assertEq(erc20Mock.balanceOf(batchDistributorAddr), 0); @@ -323,41 +213,21 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] - memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({ - recipient: alice, - amount: 50 - }); - transaction[1] = IBatchDistributor.Transaction({ - recipient: bob, - amount: 20 - }); - transaction[2] = IBatchDistributor.Transaction({ - recipient: carol, - amount: 50 - }); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ - txns: transaction - }); + IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 50}); + transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 20}); + transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 50}); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); - vm.expectRevert( - abi.encodeWithSelector( - IERC20Errors.ERC20InsufficientBalance.selector, - arg3, - 100, - 120 - ) - ); + vm.expectRevert(abi.encodeWithSelector(IERC20Errors.ERC20InsufficientBalance.selector, arg3, 100, 120)); batchDistributor.distribute_token(erc20Mock, batch); assertEq(erc20Mock.balanceOf(batchDistributorAddr), 0); vm.stopPrank(); } - function testFuzzDistributeEtherMultipleAddressesSuccess( - IBatchDistributor.Batch memory batch, - uint256 value - ) public { + function testFuzzDistributeEtherMultipleAddressesSuccess(IBatchDistributor.Batch memory batch, uint256 value) + public + { value = bound(value, type(uint16).max, type(uint32).max); vm.assume(batch.txns.length <= 50); for (uint256 i; i < batch.txns.length; ++i) { @@ -383,48 +253,27 @@ contract BatchDistributorTest is Test { address initialAccount, uint256 initialAmount ) public { - vm.assume( - initialAccount != zeroAddress && - initialAccount != batchDistributorAddr - ); - initialAmount = bound( - initialAmount, - type(uint16).max, - type(uint32).max - ); + vm.assume(initialAccount != zeroAddress && initialAccount != batchDistributorAddr); + initialAmount = bound(initialAmount, type(uint16).max, type(uint32).max); vm.assume(batch.txns.length <= 50); for (uint256 i; i < batch.txns.length; ++i) { batch.txns[i].amount = bound(batch.txns[i].amount, 1, 100); - vm.assume( - batch.txns[i].recipient != batchDistributorAddr && - batch.txns[i].recipient != zeroAddress - ); + vm.assume(batch.txns[i].recipient != batchDistributorAddr && batch.txns[i].recipient != zeroAddress); } uint256 valueAccumulator; string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; - ERC20Mock erc20Mock = new ERC20Mock( - arg1, - arg2, - initialAccount, - initialAmount - ); + ERC20Mock erc20Mock = new ERC20Mock(arg1, arg2, initialAccount, initialAmount); vm.startPrank(initialAccount); erc20Mock.approve(batchDistributorAddr, initialAmount); batchDistributor.distribute_token(erc20Mock, batch); vm.stopPrank(); for (uint256 i; i < batch.txns.length; ++i) { valueAccumulator += batch.txns[i].amount; - assertGe( - erc20Mock.balanceOf(batch.txns[i].recipient), - batch.txns[i].amount - ); + assertGe(erc20Mock.balanceOf(batch.txns[i].recipient), batch.txns[i].amount); } - assertGe( - erc20Mock.balanceOf(initialAccount), - initialAmount - valueAccumulator - ); + assertGe(erc20Mock.balanceOf(initialAccount), initialAmount - valueAccumulator); assertEq(erc20Mock.balanceOf(batchDistributorAddr), 0); } } @@ -439,21 +288,11 @@ contract BatchDistributorInvariants is Test { address private batchDistributorAddr; function setUp() public { - batchDistributor = IBatchDistributor( - vyperDeployer.deployContract("src/utils/", "BatchDistributor") - ); + batchDistributor = IBatchDistributor(vyperDeployer.deployContract("src/utils/", "BatchDistributor")); batchDistributorAddr = address(batchDistributor); address msgSender = makeAddr("msgSender"); - erc20Mock = new ERC20Mock( - "MyToken", - "MTKN", - msgSender, - type(uint256).max - ); - batchDistributorHandler = new BatchDistributorHandler( - batchDistributor, - erc20Mock - ); + erc20Mock = new ERC20Mock("MyToken", "MTKN", msgSender, type(uint256).max); + batchDistributorHandler = new BatchDistributorHandler(batchDistributor, erc20Mock); targetContract(address(batchDistributorHandler)); targetSender(msgSender); } @@ -480,9 +319,7 @@ contract BatchDistributorHandler { token = token_; } - function distribute_ether( - IBatchDistributor.Batch calldata batch - ) public payable { + function distribute_ether(IBatchDistributor.Batch calldata batch) public payable { batchDistributor.distribute_ether(batch); } diff --git a/test/utils/Create2Address.t.sol b/test/utils/Create2Address.t.sol index 52ad90f0..e4b0ad6f 100644 --- a/test/utils/Create2Address.t.sol +++ b/test/utils/Create2Address.t.sol @@ -18,9 +18,7 @@ contract Create2AddressTest is Test { address private create2AddressAddr; function setUp() public { - create2Address = ICreate2Address( - vyperDeployer.deployContract("src/utils/", "Create2Address") - ); + create2Address = ICreate2Address(vyperDeployer.deployContract("src/utils/", "Create2Address")); create2AddressAddr = address(create2Address); } @@ -31,27 +29,12 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked( - vm.getCode("ERC20Mock.sol:ERC20Mock"), - args - ); + bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address( - salt, - bytecodeHash, - address(this) - ); + address create2AddressComputed = create2Address.compute_address(salt, bytecodeHash, address(this)); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( - arg1, - arg2, - arg3, - arg4 - ); - assertEq( - create2AddressComputed, - address(create2AddressComputedOnChain) - ); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); + assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); } function testComputeAddressSelf() public { @@ -61,30 +44,16 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked( - vm.getCode("ERC20Mock.sol:ERC20Mock"), - args - ); + bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address_self( - salt, - bytecodeHash - ); - address create2AddressOZComputed = create2Impl - .computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); + address create2AddressComputed = create2Address.compute_address_self(salt, bytecodeHash); + address create2AddressOZComputed = + create2Impl.computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); vm.prank(create2AddressAddr); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); assertEq(create2AddressComputed, create2AddressOZComputed); - assertEq( - create2AddressComputed, - address(create2AddressComputedOnChain) - ); + assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); } function testFuzzComputeAddress(bytes32 salt, address deployer) public { @@ -93,28 +62,13 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked( - vm.getCode("ERC20Mock.sol:ERC20Mock"), - args - ); + bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address( - salt, - bytecodeHash, - deployer - ); + address create2AddressComputed = create2Address.compute_address(salt, bytecodeHash, deployer); vm.prank(deployer); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( - arg1, - arg2, - arg3, - arg4 - ); - assertEq( - create2AddressComputed, - address(create2AddressComputedOnChain) - ); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); + assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); } function testFuzzComputeAddressSelf(bytes32 salt) public { @@ -123,29 +77,15 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked( - vm.getCode("ERC20Mock.sol:ERC20Mock"), - args - ); + bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address_self( - salt, - bytecodeHash - ); - address create2AddressOZComputed = create2Impl - .computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); + address create2AddressComputed = create2Address.compute_address_self(salt, bytecodeHash); + address create2AddressOZComputed = + create2Impl.computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); vm.prank(create2AddressAddr); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); assertEq(create2AddressComputed, create2AddressOZComputed); - assertEq( - create2AddressComputed, - address(create2AddressComputedOnChain) - ); + assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); } } diff --git a/test/utils/CreateAddress.t.sol b/test/utils/CreateAddress.t.sol index c9116943..b4ecd769 100644 --- a/test/utils/CreateAddress.t.sol +++ b/test/utils/CreateAddress.t.sol @@ -20,9 +20,7 @@ contract CreateAddressTest is Test { address private createAddressAddr; function setUp() public { - createAddress = ICreateAddress( - vyperDeployer.deployContract("src/utils/", "CreateAddress") - ); + createAddress = ICreateAddress(vyperDeployer.deployContract("src/utils/", "CreateAddress")); createAddressAddr = address(createAddress); } @@ -41,15 +39,9 @@ contract CreateAddressTest is Test { function testComputeAddressNonce0x00() public { address alice = makeAddr("alice"); uint64 nonce = 0x00; - address createAddressComputed = createAddress.compute_address_rlp( - alice, - nonce - ); - - address createAddressComputedOnChain = create.computeAddress( - alice, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(alice, nonce); + + address createAddressComputedOnChain = create.computeAddress(alice, nonce); assertEq(createAddressComputed, createAddressComputedOnChain); } @@ -60,17 +52,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = 0x7f; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -81,17 +65,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint8).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -102,17 +78,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint16).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -123,17 +91,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint24).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -144,17 +104,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint32).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -165,17 +117,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint40).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -186,17 +130,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint48).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -207,17 +143,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint56).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -228,17 +156,9 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = uint64(type(uint64).max) - 1; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - self, - nonce - ); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + address createAddressComputed = createAddress.compute_address_rlp(self, nonce); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -249,21 +169,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = 0x7f; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -275,21 +185,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint8).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -301,21 +201,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint16).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -327,21 +217,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint24).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -353,21 +233,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint32).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -379,21 +249,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint40).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -405,21 +265,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint48).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -431,21 +281,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint56).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -457,310 +297,150 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = uint64(type(uint64).max) - 1; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressRevertTooHighNonce( - uint256 nonce, - address deployer - ) public { - nonce = bound( - nonce, - uint256(type(uint64).max), - uint256(type(uint256).max) - ); + function testFuzzComputeAddressRevertTooHighNonce(uint256 nonce, address deployer) public { + nonce = bound(nonce, uint256(type(uint64).max), uint256(type(uint256).max)); vm.expectRevert(bytes("RLP: invalid nonce value")); createAddress.compute_address_rlp(deployer, nonce); } - function testFuzzComputeAddressSelfRevertTooHighNonce( - uint256 nonce - ) public { - nonce = bound( - nonce, - uint256(type(uint64).max), - uint256(type(uint256).max) - ); + function testFuzzComputeAddressSelfRevertTooHighNonce(uint256 nonce) public { + nonce = bound(nonce, uint256(type(uint64).max), uint256(type(uint256).max)); vm.expectRevert(bytes("RLP: invalid nonce value")); createAddress.compute_address_rlp_self(nonce); } - function testFuzzComputeAddressNonce0x7f( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonce0x7f(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; nonce = uint64(bound(uint256(nonce), vm.getNonce(deployer) + 1, 0x7f)); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint8( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint8(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; nonce = uint64(bound(nonce, 0x7f + 1, uint256(type(uint8).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint16( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint16(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound(nonce, uint64(type(uint8).max) + 1, uint64(type(uint16).max)) - ); + nonce = uint64(bound(nonce, uint64(type(uint8).max) + 1, uint64(type(uint16).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint24( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint24(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint16).max) + 1, - uint256(type(uint24).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint16).max) + 1, uint256(type(uint24).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint32( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint32(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint24).max) + 1, - uint256(type(uint32).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint24).max) + 1, uint256(type(uint32).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint40( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint40(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint32).max) + 1, - uint256(type(uint40).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint32).max) + 1, uint256(type(uint40).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint48( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint48(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint40).max) + 1, - uint256(type(uint48).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint40).max) + 1, uint256(type(uint48).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint56( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint56(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint48).max) + 1, - uint256(type(uint56).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint48).max) + 1, uint256(type(uint56).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint64( - uint64 nonce, - address deployer - ) public { + function testFuzzComputeAddressNonceUint64(uint64 nonce, address deployer) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint56).max) + 1, - uint256(type(uint64).max) - 1 - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint56).max) + 1, uint256(type(uint64).max) - 1)); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp( - deployer, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -771,21 +451,11 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; nonce = uint64(bound(nonce, vm.getNonce(createAddressAddr) + 1, 0x7f)); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -795,25 +465,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound(uint256(nonce), 0x7f + 1, uint256(type(uint8).max)) - ); + nonce = uint64(bound(uint256(nonce), 0x7f + 1, uint256(type(uint8).max))); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -823,29 +481,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint8).max) + 1, - uint256(type(uint16).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint8).max) + 1, uint256(type(uint16).max))); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -855,29 +497,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint16).max) + 1, - uint256(type(uint24).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint16).max) + 1, uint256(type(uint24).max))); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -887,29 +513,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint24).max) + 1, - uint256(type(uint32).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint24).max) + 1, uint256(type(uint32).max))); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -919,29 +529,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint32).max) + 1, - uint256(type(uint40).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint32).max) + 1, uint256(type(uint40).max))); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -951,29 +545,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint40).max) + 1, - uint256(type(uint48).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint40).max) + 1, uint256(type(uint48).max))); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -983,29 +561,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint48).max) + 1, - uint256(type(uint56).max) - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint48).max) + 1, uint256(type(uint56).max))); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -1015,29 +577,13 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64( - bound( - uint256(nonce), - uint256(type(uint56).max) + 1, - uint256(type(uint64).max) - 1 - ) - ); + nonce = uint64(bound(uint256(nonce), uint256(type(uint56).max) + 1, uint256(type(uint64).max) - 1)); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self( - nonce - ); - address createAddressLibComputed = create.computeAddress( - createAddressAddr, - nonce - ); + address createAddressComputed = createAddress.compute_address_rlp_self(nonce); + address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock( - arg1, - arg2, - arg3, - arg4 - ); + ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } diff --git a/test/utils/ECDSA.t.sol b/test/utils/ECDSA.t.sol index b224dc6b..3febc6fc 100644 --- a/test/utils/ECDSA.t.sol +++ b/test/utils/ECDSA.t.sol @@ -39,9 +39,7 @@ contract ECDSATest is Test { * @param signature The secp256k1 64/65-bytes signature. * @return short The 64-bytes EIP-2098 compliant signature. */ - function to2098Format( - bytes memory signature - ) internal view returns (bytes memory) { + function to2098Format(bytes memory signature) internal view returns (bytes memory) { if (signature.length != 65) revert InvalidSignatureLength(self); if (uint8(signature[32]) >> 7 == 1) revert InvalidSignatureSValue(self); bytes memory short = signature.slice(0, 64); @@ -83,9 +81,7 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert( - abi.encodeWithSelector(InvalidSignatureLength.selector, self) - ); + vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); to2098Format(signature); } @@ -103,9 +99,7 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert( - abi.encodeWithSelector(InvalidSignatureLength.selector, self) - ); + vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); to2098Format(signature); } @@ -167,10 +161,7 @@ contract ECDSATest is Test { bytes memory signatureWithoutVersion = abi.encodePacked(r, s); bytes1 version = 0x00; vm.expectRevert(bytes("ECDSA: invalid signature")); - ECDSA.recover_sig( - hash, - abi.encodePacked(signatureWithoutVersion, version) - ); + ECDSA.recover_sig(hash, abi.encodePacked(signatureWithoutVersion, version)); } function testRecoverWithWrongVersion() public { @@ -183,10 +174,7 @@ contract ECDSATest is Test { bytes memory signatureWithoutVersion = abi.encodePacked(r, s); bytes1 version = 0x02; vm.expectRevert(bytes("ECDSA: invalid signature")); - ECDSA.recover_sig( - hash, - abi.encodePacked(signatureWithoutVersion, version) - ); + ECDSA.recover_sig(hash, abi.encodePacked(signatureWithoutVersion, version)); } function testRecoverWithCorrectVersion() public { @@ -197,20 +185,12 @@ contract ECDSATest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signatureWithoutVersion = abi.encodePacked(r, s); - assertEq( - alice, - ECDSA.recover_sig( - hash, - abi.encodePacked(signatureWithoutVersion, v) - ) - ); + assertEq(alice, ECDSA.recover_sig(hash, abi.encodePacked(signatureWithoutVersion, v))); /** * @dev EIP-2098 signature check. */ - bytes memory signature2098 = to2098Format( - abi.encodePacked(signatureWithoutVersion, v) - ); + bytes memory signature2098 = to2098Format(abi.encodePacked(signatureWithoutVersion, v)); assertEq(alice, ECDSA.recover_sig(hash, signature2098)); } @@ -221,8 +201,7 @@ contract ECDSATest is Test { (, uint256 key) = makeAddrAndKey("alice"); bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); - uint256 sTooHigh = uint256(s) + - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; + uint256 sTooHigh = uint256(s) + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; bytes memory signature = abi.encodePacked(r, bytes32(sTooHigh), v); vm.expectRevert(bytes("ECDSA: invalid signature `s` value")); ECDSA.recover_sig(hash, signature); @@ -230,18 +209,14 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert( - abi.encodeWithSelector(InvalidSignatureSValue.selector, self) - ); + vm.expectRevert(abi.encodeWithSelector(InvalidSignatureSValue.selector, self)); to2098Format(signature); } function testEthSignedMessageHash() public { bytes32 hash = keccak256("WAGMI"); bytes32 digest1 = ECDSA.to_eth_signed_message_hash(hash); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) - ); + bytes32 digest2 = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); assertEq(digest1, digest2); } @@ -249,38 +224,26 @@ contract ECDSATest is Test { bytes32 domainSeparator = keccak256("WAGMI"); bytes32 structHash = keccak256("GM"); bytes32 digest1 = ECDSA.to_typed_data_hash(domainSeparator, structHash); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19\x01", domainSeparator, structHash) - ); + bytes32 digest2 = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); assertEq(digest1, digest2); } function testToDataWithIntendedValidatorHash() public { address validator = makeAddr("intendedValidator"); bytes memory data = new bytes(42); - bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash( - validator, - data - ); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19\x00", validator, data) - ); + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash(validator, data); + bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", validator, data)); assertEq(digest1, digest2); } function testToDataWithIntendedValidatorHashSelf() public { bytes memory data = new bytes(42); bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash_self(data); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19\x00", ECDSAAddr, data) - ); + bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", ECDSAAddr, data)); assertEq(digest1, digest2); } - function testFuzzRecoverWithValidSignature( - string calldata signer, - string calldata message - ) public { + function testFuzzRecoverWithValidSignature(string calldata signer, string calldata message) public { /** * @dev Standard signature check. */ @@ -297,11 +260,7 @@ contract ECDSATest is Test { assertEq(alice, ECDSA.recover_sig(hash, signature2098)); } - function testFuzzRecoverWithWrongMessage( - string calldata signer, - string calldata message, - bytes32 digest - ) public { + function testFuzzRecoverWithWrongMessage(string calldata signer, string calldata message, bytes32 digest) public { /** * @dev Standard signature check. */ @@ -319,10 +278,7 @@ contract ECDSATest is Test { assertTrue(alice != ECDSA.recover_sig(digest, signature2098)); } - function testFuzzRecoverWithInvalidSignature( - bytes calldata signature, - string calldata message - ) public { + function testFuzzRecoverWithInvalidSignature(bytes calldata signature, string calldata message) public { vm.assume(signature.length < 64); /** * @dev Standard signature check. @@ -334,16 +290,11 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert( - abi.encodeWithSelector(InvalidSignatureLength.selector, self) - ); + vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); to2098Format(signature); } - function testFuzzRecoverWithTooLongSignature( - bytes calldata signature, - string calldata message - ) public { + function testFuzzRecoverWithTooLongSignature(bytes calldata signature, string calldata message) public { vm.assume(signature.length > 65); /** * @dev Standard signature check. @@ -355,55 +306,34 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert( - abi.encodeWithSelector(InvalidSignatureLength.selector, self) - ); + vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); to2098Format(signature); } function testFuzzEthSignedMessageHash(string calldata message) public { bytes32 hash = keccak256(abi.encode(message)); bytes32 digest1 = ECDSA.to_eth_signed_message_hash(hash); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) - ); + bytes32 digest2 = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); assertEq(digest1, digest2); } - function testFuzzToTypedDataHash( - string calldata domainSeparatorPlain, - string calldata structPlain - ) public { + function testFuzzToTypedDataHash(string calldata domainSeparatorPlain, string calldata structPlain) public { bytes32 domainSeparator = keccak256(abi.encode(domainSeparatorPlain)); bytes32 structHash = keccak256(abi.encode(structPlain)); bytes32 digest1 = ECDSA.to_typed_data_hash(domainSeparator, structHash); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19\x01", domainSeparator, structHash) - ); + bytes32 digest2 = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); assertEq(digest1, digest2); } - function testFuzzToDataWithIntendedValidatorHash( - address validator, - bytes calldata data - ) public { - bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash( - validator, - data - ); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19\x00", validator, data) - ); + function testFuzzToDataWithIntendedValidatorHash(address validator, bytes calldata data) public { + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash(validator, data); + bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", validator, data)); assertEq(digest1, digest2); } - function testFuzzToDataWithIntendedValidatorHashSelf( - bytes calldata data - ) public { + function testFuzzToDataWithIntendedValidatorHashSelf(bytes calldata data) public { bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash_self(data); - bytes32 digest2 = keccak256( - abi.encodePacked("\x19\x00", ECDSAAddr, data) - ); + bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", ECDSAAddr, data)); assertEq(digest1, digest2); } } diff --git a/test/utils/EIP712DomainSeparator.t.sol b/test/utils/EIP712DomainSeparator.t.sol index 08c98f48..c0d81c18 100644 --- a/test/utils/EIP712DomainSeparator.t.sol +++ b/test/utils/EIP712DomainSeparator.t.sol @@ -10,17 +10,9 @@ contract EIP712DomainSeparatorTest is Test { string private constant _NAME = "WAGMI"; string private constant _VERSION = "1"; bytes32 private constant _TYPE_HASH = - keccak256( - bytes( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ) - ); + keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256( - bytes( - "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" - ) - ); + keccak256(bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")); VyperDeployer private vyperDeployer = new VyperDeployer(); @@ -34,13 +26,8 @@ contract EIP712DomainSeparatorTest is Test { function setUp() public { bytes memory args = abi.encode(_NAME, _VERSION); - EIP712domainSeparator = IEIP712DomainSeparator( - vyperDeployer.deployContract( - "src/utils/", - "EIP712DomainSeparator", - args - ) - ); + EIP712domainSeparator = + IEIP712DomainSeparator(vyperDeployer.deployContract("src/utils/", "EIP712DomainSeparator", args)); EIP712domainSeparatorAddr = address(EIP712domainSeparator); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( @@ -54,10 +41,7 @@ contract EIP712DomainSeparatorTest is Test { } function testCachedDomainSeparatorV4() public { - assertEq( - EIP712domainSeparator.domain_separator_v4(), - _CACHED_DOMAIN_SEPARATOR - ); + assertEq(EIP712domainSeparator.domain_separator_v4(), _CACHED_DOMAIN_SEPARATOR); } function testDomainSeparatorV4() public { @@ -85,24 +69,10 @@ contract EIP712DomainSeparatorTest is Test { uint256 nonce = 1; // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 structHash = keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - value, - nonce, - deadline - ) - ); + bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, value, nonce, deadline)); bytes32 digest1 = EIP712domainSeparator.hash_typed_data_v4(structHash); - bytes32 digest2 = keccak256( - abi.encodePacked( - "\x19\x01", - EIP712domainSeparator.domain_separator_v4(), - structHash - ) - ); + bytes32 digest2 = + keccak256(abi.encodePacked("\x19\x01", EIP712domainSeparator.domain_separator_v4(), structHash)); assertEq(digest1, digest2); } @@ -125,13 +95,7 @@ contract EIP712DomainSeparatorTest is Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(EIP712domainSeparator.domain_separator_v4(), digest); } @@ -154,33 +118,15 @@ contract EIP712DomainSeparatorTest is Test { assertEq(EIP712domainSeparator.domain_separator_v4(), digest); } - function testFuzzHashTypedDataV4( - address owner, - address spender, - uint256 value, - uint256 nonce, - uint64 increment - ) public { + function testFuzzHashTypedDataV4(address owner, address spender, uint256 value, uint256 nonce, uint64 increment) + public + { // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; - bytes32 structHash = keccak256( - abi.encode( - _PERMIT_TYPE_HASH, - owner, - spender, - value, - nonce, - deadline - ) - ); + bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, value, nonce, deadline)); bytes32 digest1 = EIP712domainSeparator.hash_typed_data_v4(structHash); - bytes32 digest2 = keccak256( - abi.encodePacked( - "\x19\x01", - EIP712domainSeparator.domain_separator_v4(), - structHash - ) - ); + bytes32 digest2 = + keccak256(abi.encodePacked("\x19\x01", EIP712domainSeparator.domain_separator_v4(), structHash)); assertEq(digest1, digest2); } @@ -190,11 +136,7 @@ contract EIP712DomainSeparatorTest is Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume( - randomHex != hex"0f" && - randomSalt != bytes32(0) && - randomExtensions.length != 0 - ); + vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -211,19 +153,10 @@ contract EIP712DomainSeparatorTest is Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, EIP712domainSeparatorAddr); assertTrue(salt != randomSalt); - assertTrue( - keccak256(abi.encode(extensions)) != - keccak256(abi.encode(randomExtensions)) - ); + assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); bytes32 digest = keccak256( - abi.encode( - _TYPE_HASH, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - verifyingContract - ) + abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) ); assertEq(EIP712domainSeparator.domain_separator_v4(), digest); } diff --git a/test/utils/Math.t.sol b/test/utils/Math.t.sol index 325f911d..e2ca5032 100644 --- a/test/utils/Math.t.sol +++ b/test/utils/Math.t.sol @@ -23,11 +23,7 @@ contract MathTest is Test { * @param denominator The 32-byte divisor. * @return result The 32-byte result of the `mulmod` operation. */ - function mulMod( - uint256 x, - uint256 y, - uint256 denominator - ) internal pure returns (uint256 result) { + function mulMod(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { // solhint-disable-next-line no-inline-assembly assembly { result := mulmod(x, y, denominator) @@ -42,10 +38,7 @@ contract MathTest is Test { * @return high The most significant 32 bytes of the product. * @return low The least significant 32 bytes of the product. */ - function mulHighLow( - uint256 x, - uint256 y - ) internal pure returns (uint256 high, uint256 low) { + function mulHighLow(uint256 x, uint256 y) internal pure returns (uint256 high, uint256 low) { (uint256 x0, uint256 x1) = (x & type(uint128).max, x >> 128); (uint256 y0, uint256 y1) = (y & type(uint128).max, y >> 128); @@ -57,9 +50,7 @@ contract MathTest is Test { uint256 z1b = x0 * y1; uint256 z0 = x0 * y0; - uint256 carry = ((z1a & type(uint128).max) + - (z1b & type(uint128).max) + - (z0 >> 128)) >> 128; + uint256 carry = ((z1a & type(uint128).max) + (z1b & type(uint128).max) + (z0 >> 128)) >> 128; high = z2 + (z1a >> 128) + (z1b >> 128) + carry; @@ -76,10 +67,7 @@ contract MathTest is Test { * @return remainder The 32-byte remainder. * @return carry The 32-byte carry. */ - function addCarry( - uint256 x, - uint256 y - ) internal pure returns (uint256 remainder, uint256 carry) { + function addCarry(uint256 x, uint256 y) internal pure returns (uint256 remainder, uint256 carry) { unchecked { remainder = x + y; } @@ -118,10 +106,7 @@ contract MathTest is Test { assertEq(math.uint256_average(73_220, 419_712), 246_466); assertEq(math.uint256_average(83_219, 419_712), 251_465); assertEq(math.uint256_average(73_220, 219_713), 146_466); - assertEq( - math.uint256_average(type(uint256).max, type(uint256).max), - type(uint256).max - ); + assertEq(math.uint256_average(type(uint256).max, type(uint256).max), type(uint256).max); } function testInt256Average() public { @@ -137,10 +122,7 @@ contract MathTest is Test { assertEq(math.int256_average(73_220, 219_713), 146_466); assertEq(math.int256_average(-73_220, -219_713), -146_467); - assertEq( - math.int256_average(type(int256).min, type(int256).min), - type(int256).min - ); + assertEq(math.int256_average(type(int256).min, type(int256).min), type(int256).min); assertEq(math.int256_average(type(int256).min, type(int256).max), -1); } @@ -192,18 +174,9 @@ contract MathTest is Test { uint256 maxUint256Sub2 = maxUint256 - 2; assertEq(math.mul_div(42, maxUint256Sub1, maxUint256, false), 41); assertEq(math.mul_div(23, maxUint256, maxUint256, false), 23); - assertEq( - math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, false), - maxUint256Sub2 - ); - assertEq( - math.mul_div(maxUint256, maxUint256Sub1, maxUint256, false), - maxUint256Sub1 - ); - assertEq( - math.mul_div(maxUint256, maxUint256, maxUint256, false), - maxUint256 - ); + assertEq(math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, false), maxUint256Sub2); + assertEq(math.mul_div(maxUint256, maxUint256Sub1, maxUint256, false), maxUint256Sub1); + assertEq(math.mul_div(maxUint256, maxUint256, maxUint256, false), maxUint256); } function testMulDivRoundUpSmallValues() public { @@ -217,18 +190,9 @@ contract MathTest is Test { uint256 maxUint256Sub1 = maxUint256 - 1; assertEq(math.mul_div(42, maxUint256Sub1, maxUint256, true), 42); assertEq(math.mul_div(23, maxUint256, maxUint256, true), 23); - assertEq( - math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, true), - maxUint256Sub1 - ); - assertEq( - math.mul_div(maxUint256, maxUint256Sub1, maxUint256, true), - maxUint256Sub1 - ); - assertEq( - math.mul_div(maxUint256, maxUint256, maxUint256, true), - maxUint256 - ); + assertEq(math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, true), maxUint256Sub1); + assertEq(math.mul_div(maxUint256, maxUint256Sub1, maxUint256, true), maxUint256Sub1); + assertEq(math.mul_div(maxUint256, maxUint256, maxUint256, true), maxUint256); } function testLog2RoundDown() public { @@ -324,14 +288,8 @@ contract MathTest is Test { assertEq(math.wad_ln(42), -37_708_862_055_609_454_007); assertEq(math.wad_ln(10 ** 4), -32_236_191_301_916_639_577); assertEq(math.wad_ln(10 ** 9), -20_723_265_836_946_411_157); - assertEq( - math.wad_ln(2_718_281_828_459_045_235), - 999_999_999_999_999_999 - ); - assertEq( - math.wad_ln(11_723_640_096_265_400_935), - 2_461_607_324_344_817_918 - ); + assertEq(math.wad_ln(2_718_281_828_459_045_235), 999_999_999_999_999_999); + assertEq(math.wad_ln(11_723_640_096_265_400_935), 2_461_607_324_344_817_918); assertEq(math.wad_ln(2 ** 128), 47_276_307_437_780_177_293); assertEq(math.wad_ln(2 ** 170), 76_388_489_021_297_880_288); assertEq(math.wad_ln(type(int256).max), 135_305_999_368_893_231_589); @@ -359,10 +317,7 @@ contract MathTest is Test { assertEq(math.wad_exp(2 * 10 ** 18), 7_389_056_098_930_650_227); assertEq(math.wad_exp(3 * 10 ** 18), 20_085_536_923_187_667_741); assertEq(math.wad_exp(10 * 10 ** 18), 22_026_465_794_806_716_516_980); - assertEq( - math.wad_exp(50 * 10 ** 18), - 5_184_705_528_587_072_464_148_529_318_587_763_226_117 - ); + assertEq(math.wad_exp(50 * 10 ** 18), 5_184_705_528_587_072_464_148_529_318_587_763_226_117); assertEq( math.wad_exp(100 * 10 ** 18), 26_881_171_418_161_354_484_134_666_106_240_937_146_178_367_581_647_816_351_662_017 @@ -397,10 +352,7 @@ contract MathTest is Test { assertEq(math.cbrt(type(uint32).max, false), 1_625); assertEq(math.cbrt(type(uint64).max, false), 2_642_245); assertEq(math.cbrt(type(uint128).max, false), 6_981_463_658_331); - assertEq( - math.cbrt(type(uint256).max, false), - 48_740_834_812_604_276_470_692_694 - ); + assertEq(math.cbrt(type(uint256).max, false), 48_740_834_812_604_276_470_692_694); } function testCbrtRoundUp() public { @@ -420,10 +372,7 @@ contract MathTest is Test { assertEq(math.cbrt(type(uint32).max, true), 1_626); assertEq(math.cbrt(type(uint64).max, true), 2_642_246); assertEq(math.cbrt(type(uint128).max, true), 6_981_463_658_332); - assertEq( - math.cbrt(type(uint256).max, true), - 48_740_834_812_604_276_470_692_695 - ); + assertEq(math.cbrt(type(uint256).max, true), 48_740_834_812_604_276_470_692_695); } function testWadCbrt() public { @@ -442,14 +391,8 @@ contract MathTest is Test { assertEq(math.wad_cbrt(type(uint16).max), 40_317_268_530_317); assertEq(math.wad_cbrt(type(uint32).max), 1_625_498_677_089_280); assertEq(math.wad_cbrt(type(uint64).max), 2_642_245_949_629_133_047); - assertEq( - math.wad_cbrt(type(uint128).max), - 6_981_463_658_331_559_092_288_464 - ); - assertEq( - math.wad_cbrt(type(uint256).max), - 48_740_834_812_604_276_470_692_694_000_000_000_000 - ); + assertEq(math.wad_cbrt(type(uint128).max), 6_981_463_658_331_559_092_288_464); + assertEq(math.wad_cbrt(type(uint256).max), 48_740_834_812_604_276_470_692_694_000_000_000_000); } /** @@ -541,7 +484,7 @@ contract MathTest is Test { * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/test/utils/math/Math.t.sol. */ function testFuzzMulDivDomain(uint256 x, uint256 y, uint256 d) public { - (uint256 xyHi, ) = mulHighLow(x, y); + (uint256 xyHi,) = mulHighLow(x, y); /** * @dev Violate `testFuzzMulDiv` assumption, i.e. `d` is 0 and result overflows. @@ -655,9 +598,7 @@ contract MathTest is Test { function testFuzzWadCbrt(uint256 x) public { uint256 result = math.wad_cbrt(x); uint256 floor = floorCbrt(x); - assertTrue( - result >= floor * 10 ** 12 && result <= (floor + 1) * 10 ** 12 - ); + assertTrue(result >= floor * 10 ** 12 && result <= (floor + 1) * 10 ** 12); assertEq(result / 10 ** 12, floor); } } diff --git a/test/utils/MerkleProofVerification.t.sol b/test/utils/MerkleProofVerification.t.sol index e5cd347e..478e5f82 100644 --- a/test/utils/MerkleProofVerification.t.sol +++ b/test/utils/MerkleProofVerification.t.sol @@ -27,17 +27,8 @@ contract MerkleProofVerificationTest is Test { cmdsProof[0] = "node"; cmdsProof[1] = "test/utils/scripts/generate-proof.js"; bytes memory proof = vm.ffi(cmdsProof); - ( - bytes32 arg1, - bytes32 arg2, - bytes32 arg3, - bytes32 arg4, - bytes32 arg5, - bytes32 arg6 - ) = abi.decode( - proof, - (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32) - ); + (bytes32 arg1, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5, bytes32 arg6) = + abi.decode(proof, (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32)); proofDecoded[0] = arg1; proofDecoded[1] = arg2; proofDecoded[2] = arg3; @@ -54,37 +45,14 @@ contract MerkleProofVerificationTest is Test { * @return bytes32[] The 32-byte array containing sibling hashes * on the branches from `leaves` to the `root` of the Merkle tree. */ - function decodeCorrectMultiProofPayload() - internal - returns (bytes32[] memory) - { + function decodeCorrectMultiProofPayload() internal returns (bytes32[] memory) { bytes32[] memory multiProofDecoded = new bytes32[](8); string[] memory cmdsMultiProof = new string[](2); cmdsMultiProof[0] = "node"; cmdsMultiProof[1] = "test/utils/scripts/generate-multiproof.js"; bytes memory multiProof = vm.ffi(cmdsMultiProof); - ( - bytes32 arg1, - bytes32 arg2, - bytes32 arg3, - bytes32 arg4, - bytes32 arg5, - bytes32 arg6, - bytes32 arg7, - bytes32 arg8 - ) = abi.decode( - multiProof, - ( - bytes32, - bytes32, - bytes32, - bytes32, - bytes32, - bytes32, - bytes32, - bytes32 - ) - ); + (bytes32 arg1, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5, bytes32 arg6, bytes32 arg7, bytes32 arg8) + = abi.decode(multiProof, (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32)); multiProofDecoded[0] = arg1; multiProofDecoded[1] = arg2; multiProofDecoded[2] = arg3; @@ -104,32 +72,14 @@ contract MerkleProofVerificationTest is Test { * value from the "main queue" (merging branches) or an element from the * `proof` array is used to calculate the next hash. */ - function decodeCorrectMultiProofProofFlags() - internal - returns (bool[] memory) - { + function decodeCorrectMultiProofProofFlags() internal returns (bool[] memory) { bool[] memory multiProofProofFlagsDecoded = new bool[](10); string[] memory cmdsMultiProofProofFlags = new string[](2); cmdsMultiProofProofFlags[0] = "node"; - cmdsMultiProofProofFlags[ - 1 - ] = "test/utils/scripts/generate-multiproof-proof-flags.js"; + cmdsMultiProofProofFlags[1] = "test/utils/scripts/generate-multiproof-proof-flags.js"; bytes memory multiProofProofFlags = vm.ffi(cmdsMultiProofProofFlags); - ( - bool arg1, - bool arg2, - bool arg3, - bool arg4, - bool arg5, - bool arg6, - bool arg7, - bool arg8, - bool arg9, - bool arg10 - ) = abi.decode( - multiProofProofFlags, - (bool, bool, bool, bool, bool, bool, bool, bool, bool, bool) - ); + (bool arg1, bool arg2, bool arg3, bool arg4, bool arg5, bool arg6, bool arg7, bool arg8, bool arg9, bool arg10) + = abi.decode(multiProofProofFlags, (bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)); multiProofProofFlagsDecoded[0] = arg1; multiProofProofFlagsDecoded[1] = arg2; multiProofProofFlagsDecoded[2] = arg3; @@ -153,27 +103,14 @@ contract MerkleProofVerificationTest is Test { * @return bytes32[] The 32-byte array containing sibling hashes * on the branch from the `leaf` to the `root` of the Merkle tree. */ - function decodeNoSuchLeafProofPayload() - internal - returns (bytes32[] memory) - { + function decodeNoSuchLeafProofPayload() internal returns (bytes32[] memory) { bytes32[] memory proofDecodedSliced = new bytes32[](6); string[] memory cmdsProof = new string[](2); cmdsProof[0] = "node"; cmdsProof[1] = "test/utils/scripts/generate-proof-no-such-leaf.js"; bytes memory proof = vm.ffi(cmdsProof); - ( - , - bytes32 arg2, - bytes32 arg3, - bytes32 arg4, - bytes32 arg5, - bytes32 arg6, - bytes32 arg7 - ) = abi.decode( - proof, - (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32) - ); + (, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5, bytes32 arg6, bytes32 arg7) = + abi.decode(proof, (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32)); proofDecodedSliced[0] = arg2; proofDecodedSliced[1] = arg3; proofDecodedSliced[2] = arg4; @@ -216,16 +153,8 @@ contract MerkleProofVerificationTest is Test { cmdsMultiProof[0] = "node"; cmdsMultiProof[1] = "test/utils/scripts/generate-bad-multiproof.js"; bytes memory multiProof = vm.ffi(cmdsMultiProof); - ( - bytes32 arg1, - bytes32 arg2, - bytes32 arg3, - bytes32 arg4, - bytes32 arg5 - ) = abi.decode( - multiProof, - (bytes32, bytes32, bytes32, bytes32, bytes32) - ); + (bytes32 arg1, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5) = + abi.decode(multiProof, (bytes32, bytes32, bytes32, bytes32, bytes32)); multiProofDecoded[0] = arg1; multiProofDecoded[1] = arg2; multiProofDecoded[2] = arg3; @@ -248,22 +177,10 @@ contract MerkleProofVerificationTest is Test { bool[] memory multiProofProofFlagsDecoded = new bool[](7); string[] memory cmdsMultiProofProofFlags = new string[](2); cmdsMultiProofProofFlags[0] = "node"; - cmdsMultiProofProofFlags[ - 1 - ] = "test/utils/scripts/generate-bad-multiproof-proof-flags.js"; + cmdsMultiProofProofFlags[1] = "test/utils/scripts/generate-bad-multiproof-proof-flags.js"; bytes memory multiProofProofFlags = vm.ffi(cmdsMultiProofProofFlags); - ( - bool arg1, - bool arg2, - bool arg3, - bool arg4, - bool arg5, - bool arg6, - bool arg7 - ) = abi.decode( - multiProofProofFlags, - (bool, bool, bool, bool, bool, bool, bool) - ); + (bool arg1, bool arg2, bool arg3, bool arg4, bool arg5, bool arg6, bool arg7) = + abi.decode(multiProofProofFlags, (bool, bool, bool, bool, bool, bool, bool)); multiProofProofFlagsDecoded[0] = arg1; multiProofProofFlagsDecoded[1] = arg2; multiProofProofFlagsDecoded[2] = arg3; @@ -275,12 +192,8 @@ contract MerkleProofVerificationTest is Test { } function setUp() public { - merkleProofVerification = IMerkleProofVerification( - vyperDeployer.deployContract( - "src/utils/", - "MerkleProofVerification" - ) - ); + merkleProofVerification = + IMerkleProofVerification(vyperDeployer.deployContract("src/utils/", "MerkleProofVerification")); } function testVerify() public { @@ -296,19 +209,11 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory proofDecoded = decodeCorrectProofPayload(); - assertTrue( - merkleProofVerification.verify( - proofDecoded, - bytes32(root), - bytes32(leaf) - ) - ); + assertTrue(merkleProofVerification.verify(proofDecoded, bytes32(root), bytes32(leaf))); string[] memory cmdsRootNoSuchLeaf = new string[](2); cmdsRootNoSuchLeaf[0] = "node"; - cmdsRootNoSuchLeaf[ - 1 - ] = "test/utils/scripts/generate-root-no-such-leaf.js"; + cmdsRootNoSuchLeaf[1] = "test/utils/scripts/generate-root-no-such-leaf.js"; bytes memory rootNoSuchLeaf = vm.ffi(cmdsRootNoSuchLeaf); string[] memory cmdsNoSuchLeaf = new string[](2); @@ -318,13 +223,7 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory proofDecodedSliced = decodeNoSuchLeafProofPayload(); - assertTrue( - merkleProofVerification.verify( - proofDecodedSliced, - bytes32(rootNoSuchLeaf), - bytes32(noSuchLeaf) - ) - ); + assertTrue(merkleProofVerification.verify(proofDecodedSliced, bytes32(rootNoSuchLeaf), bytes32(noSuchLeaf))); } function testInvalidMerkleProof() public { @@ -340,13 +239,7 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory badProofDecoded = decodeBadProofPayload(); - assertTrue( - !merkleProofVerification.verify( - badProofDecoded, - bytes32(correctRoot), - bytes32(leaf) - ) - ); + assertTrue(!merkleProofVerification.verify(badProofDecoded, bytes32(correctRoot), bytes32(leaf))); } function testInvalidMerkleProofLength() public { @@ -367,13 +260,7 @@ contract MerkleProofVerificationTest is Test { proofInvalidLengthDecoded[1] = proofDecoded[1]; proofInvalidLengthDecoded[2] = proofDecoded[2]; - assertTrue( - !merkleProofVerification.verify( - proofInvalidLengthDecoded, - bytes32(root), - bytes32(leaf) - ) - ); + assertTrue(!merkleProofVerification.verify(proofInvalidLengthDecoded, bytes32(root), bytes32(leaf))); } function testMultiProofVerify() public { @@ -387,10 +274,7 @@ contract MerkleProofVerificationTest is Test { cmdsLeaves[1] = "test/utils/scripts/generate-multiproof-leaves.js"; bytes memory leaves = vm.ffi(cmdsLeaves); bytes32[] memory leavesDecoded = new bytes32[](3); - (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode( - leaves, - (bytes32, bytes32, bytes32) - ); + (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode(leaves, (bytes32, bytes32, bytes32)); leavesDecoded[0] = arg1; leavesDecoded[1] = arg2; leavesDecoded[2] = arg3; @@ -399,12 +283,7 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory multiProofDecoded = decodeCorrectMultiProofPayload(); assertTrue( - merkleProofVerification.multi_proof_verify( - multiProofDecoded, - proofFlags, - bytes32(root), - leavesDecoded - ) + merkleProofVerification.multi_proof_verify(multiProofDecoded, proofFlags, bytes32(root), leavesDecoded) ); } @@ -416,15 +295,10 @@ contract MerkleProofVerificationTest is Test { string[] memory cmdsBadLeaves = new string[](2); cmdsBadLeaves[0] = "node"; - cmdsBadLeaves[ - 1 - ] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; + cmdsBadLeaves[1] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; bytes memory badLeaves = vm.ffi(cmdsBadLeaves); bytes32[] memory badLeavesDecoded = new bytes32[](3); - (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode( - badLeaves, - (bytes32, bytes32, bytes32) - ); + (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode(badLeaves, (bytes32, bytes32, bytes32)); badLeavesDecoded[0] = arg1; badLeavesDecoded[1] = arg2; badLeavesDecoded[2] = arg3; @@ -434,10 +308,7 @@ contract MerkleProofVerificationTest is Test { assertTrue( !merkleProofVerification.multi_proof_verify( - badMultiProofDecoded, - badProofFlags, - bytes32(correctRoot), - badLeavesDecoded + badMultiProofDecoded, badProofFlags, bytes32(correctRoot), badLeavesDecoded ) ); } @@ -476,12 +347,7 @@ contract MerkleProofVerificationTest is Test { maliciousProofFlags[2] = false; vm.expectRevert(); - merkleProofVerification.multi_proof_verify( - maliciousProof, - maliciousProofFlags, - root, - maliciousLeaves - ); + merkleProofVerification.multi_proof_verify(maliciousProof, maliciousProofFlags, root, maliciousLeaves); } function testInvalidMultiProof() public { @@ -492,15 +358,10 @@ contract MerkleProofVerificationTest is Test { string[] memory cmdsBadLeaves = new string[](2); cmdsBadLeaves[0] = "node"; - cmdsBadLeaves[ - 1 - ] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; + cmdsBadLeaves[1] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; bytes memory badLeaves = vm.ffi(cmdsBadLeaves); bytes32[] memory badLeavesDecoded = new bytes32[](3); - (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode( - badLeaves, - (bytes32, bytes32, bytes32) - ); + (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode(badLeaves, (bytes32, bytes32, bytes32)); badLeavesDecoded[0] = arg1; badLeavesDecoded[1] = arg2; badLeavesDecoded[2] = arg3; @@ -524,26 +385,17 @@ contract MerkleProofVerificationTest is Test { vm.expectRevert(bytes("MerkleProof: invalid multiproof")); merkleProofVerification.multi_proof_verify( - badMultiProofDecodedSliced, - badProofFlags, - bytes32(correctRoot), - badLeavesDecoded + badMultiProofDecodedSliced, badProofFlags, bytes32(correctRoot), badLeavesDecoded ); vm.expectRevert(bytes("MerkleProof: invalid multiproof")); merkleProofVerification.multi_proof_verify( - badMultiProofDecoded, - badProofFlagsSliced, - bytes32(correctRoot), - badLeavesDecoded + badMultiProofDecoded, badProofFlagsSliced, bytes32(correctRoot), badLeavesDecoded ); vm.expectRevert(bytes("MerkleProof: invalid multiproof")); merkleProofVerification.multi_proof_verify( - badMultiProofDecoded, - badProofFlags, - bytes32(correctRoot), - badLeavesDecodedSliced + badMultiProofDecoded, badProofFlags, bytes32(correctRoot), badLeavesDecodedSliced ); } @@ -557,14 +409,7 @@ contract MerkleProofVerificationTest is Test { /** * @dev Works for a Merkle tree containing a single leaf. */ - assertTrue( - merkleProofVerification.multi_proof_verify( - multiProof, - proofFlags, - leaves[0], - leaves - ) - ); + assertTrue(merkleProofVerification.multi_proof_verify(multiProof, proofFlags, leaves[0], leaves)); } function testMultiProofEdgeCase2() public { @@ -572,65 +417,38 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory multiProof = new bytes32[](1); bool[] memory proofFlags = new bool[](0); - bytes32 root = keccak256( - bytes.concat(keccak256(abi.encode("a", "b", "c"))) - ); + bytes32 root = keccak256(bytes.concat(keccak256(abi.encode("a", "b", "c")))); multiProof[0] = root; /** * @dev Can prove empty leaves. */ - assertTrue( - merkleProofVerification.multi_proof_verify( - multiProof, - proofFlags, - root, - leaves - ) - ); + assertTrue(merkleProofVerification.multi_proof_verify(multiProof, proofFlags, root, leaves)); } /** * @notice Forked and adjusted accordingly from here: * https://github.com/Vectorized/solady/blob/main/test/MerkleProofLib.t.sol. */ - function testFuzzVerify( - bytes32[] calldata data, - uint256 randomness - ) public { + function testFuzzVerify(bytes32[] calldata data, uint256 randomness) public { vm.assume(data.length > 1); uint256 nodeIndex = randomness % data.length; bytes32 root = merkleGenerator.getRoot(data); bytes32[] memory proof = merkleGenerator.getProof(data, nodeIndex); bytes32 leaf = data[nodeIndex]; assertTrue(merkleProofVerification.verify(proof, root, leaf)); - assertTrue( - !merkleProofVerification.verify( - proof, - bytes32(uint256(root) ^ 1), - leaf - ) - ); + assertTrue(!merkleProofVerification.verify(proof, bytes32(uint256(root) ^ 1), leaf)); proof[0] = bytes32(uint256(proof[0]) ^ 1); assertTrue(!merkleProofVerification.verify(proof, root, leaf)); - assertTrue( - !merkleProofVerification.verify( - proof, - bytes32(uint256(root) ^ 1), - leaf - ) - ); + assertTrue(!merkleProofVerification.verify(proof, bytes32(uint256(root) ^ 1), leaf)); } /** * @notice Forked and adjusted accordingly from here: * https://github.com/Vectorized/solady/blob/main/test/MerkleProofLib.t.sol. */ - function testFuzzMultiProofVerifySingleLeaf( - bytes32[] calldata data, - uint256 randomness - ) public { + function testFuzzMultiProofVerifySingleLeaf(bytes32[] calldata data, uint256 randomness) public { vm.assume(data.length > 1); uint256 nodeIndex = randomness % data.length; bytes32 root = merkleGenerator.getRoot(data); @@ -638,51 +456,19 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory leaves = new bytes32[](1); leaves[0] = data[nodeIndex]; bool[] memory proofFlags = new bool[](proof.length); - assertTrue( - merkleProofVerification.multi_proof_verify( - proof, - proofFlags, - root, - leaves - ) - ); - assertTrue( - !merkleProofVerification.multi_proof_verify( - proof, - proofFlags, - bytes32(uint256(root) ^ 1), - leaves - ) - ); + assertTrue(merkleProofVerification.multi_proof_verify(proof, proofFlags, root, leaves)); + assertTrue(!merkleProofVerification.multi_proof_verify(proof, proofFlags, bytes32(uint256(root) ^ 1), leaves)); proof[0] = bytes32(uint256(proof[0]) ^ 1); - assertTrue( - !merkleProofVerification.multi_proof_verify( - proof, - proofFlags, - root, - leaves - ) - ); - assertTrue( - !merkleProofVerification.multi_proof_verify( - proof, - proofFlags, - bytes32(uint256(root) ^ 1), - leaves - ) - ); + assertTrue(!merkleProofVerification.multi_proof_verify(proof, proofFlags, root, leaves)); + assertTrue(!merkleProofVerification.multi_proof_verify(proof, proofFlags, bytes32(uint256(root) ^ 1), leaves)); } /** * @notice Forked and adjusted accordingly from here: * https://github.com/Vectorized/solady/blob/main/test/MerkleProofLib.t.sol. */ - function testFuzzVerifyMultiProofMultipleLeaves( - bool damageProof, - bool damageRoot, - bool damageLeaves - ) public { + function testFuzzVerifyMultiProofMultipleLeaves(bool damageProof, bool damageRoot, bool damageLeaves) public { bool noDamage = true; bytes32 root = merkleGenerator.hashLeafPairs( @@ -723,14 +509,6 @@ contract MerkleProofVerificationTest is Test { proof[0] = bytes32(uint256(proof[0]) ^ 1); } - assertEq( - merkleProofVerification.multi_proof_verify( - proof, - flags, - root, - leaves - ), - noDamage - ); + assertEq(merkleProofVerification.multi_proof_verify(proof, flags, root, leaves), noDamage); } } diff --git a/test/utils/Multicall.t.sol b/test/utils/Multicall.t.sol index 62b7294d..df051faf 100644 --- a/test/utils/Multicall.t.sol +++ b/test/utils/Multicall.t.sol @@ -20,108 +20,52 @@ contract MulticallTest is Test { address private mockCalleeAddr = address(mockCallee); function setUp() public { - multicall = IMulticall( - vyperDeployer.deployContract("src/utils/", "Multicall") - ); + multicall = IMulticall(vyperDeployer.deployContract("src/utils/", "Multicall")); } function testMulticallSuccess() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](3); - batch[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch[1] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("store(uint256)", type(uint256).max) - ); - batch[2] = IMulticall.Batch( - mockCalleeAddr, - true, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch[1] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); + batch[2] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); IMulticall.Result[] memory results = multicall.multicall(batch); assertTrue(results[0].success); - assertEq( - keccak256(results[0].returnData), - keccak256(abi.encodePacked(blockhash(block.number))) - ); - assertEq( - keccak256(results[1].returnData), - keccak256(abi.encodePacked(abi.encode(true))) - ); + assertEq(keccak256(results[0].returnData), keccak256(abi.encodePacked(blockhash(block.number)))); + assertEq(keccak256(results[1].returnData), keccak256(abi.encodePacked(abi.encode(true)))); assertEq(mockCallee.number(), type(uint256).max); assertTrue(!results[2].success); } function testMulticallRevert() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](3); - batch[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch[1] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("store(uint256)", type(uint256).max) - ); - batch[2] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch[1] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); + batch[2] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("thisMethodReverts()")); - vm.expectRevert( - abi.encodeWithSelector(Reverted.selector, mockCalleeAddr) - ); + vm.expectRevert(abi.encodeWithSelector(Reverted.selector, mockCalleeAddr)); multicall.multicall(batch); } function testMulticallValueSuccess() public { - IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[]( - 4 - ); + IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[](4); batchValue[0] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 0, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) + mockCalleeAddr, false, 0, abi.encodeWithSignature("getBlockHash(uint256)", block.number) ); batchValue[1] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 0, - abi.encodeWithSignature("store(uint256)", type(uint256).max) - ); - batchValue[2] = IMulticall.BatchValue( - mockCalleeAddr, - true, - 0, - abi.encodeWithSignature("thisMethodReverts()") + mockCalleeAddr, false, 0, abi.encodeWithSignature("store(uint256)", type(uint256).max) ); + batchValue[2] = IMulticall.BatchValue(mockCalleeAddr, true, 0, abi.encodeWithSignature("thisMethodReverts()")); batchValue[3] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 1, - abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) + mockCalleeAddr, false, 1, abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) ); - IMulticall.Result[] memory results = multicall.multicall_value{ - value: 1 - }(batchValue); + IMulticall.Result[] memory results = multicall.multicall_value{value: 1}(batchValue); assertTrue(results[0].success); - assertEq( - keccak256(results[0].returnData), - keccak256(abi.encodePacked(blockhash(block.number))) - ); - assertEq( - keccak256(results[1].returnData), - keccak256(abi.encodePacked(abi.encode(true))) - ); + assertEq(keccak256(results[0].returnData), keccak256(abi.encodePacked(blockhash(block.number)))); + assertEq(keccak256(results[1].returnData), keccak256(abi.encodePacked(abi.encode(true)))); assertEq(mockCallee.number(), type(uint256).max); assertEq(etherReceiverAddr.balance, 1 wei); assertTrue(!results[2].success); @@ -129,70 +73,36 @@ contract MulticallTest is Test { } function testMulticallValueRevertCase1() public { - IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[]( - 4 - ); + IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[](4); batchValue[0] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 0, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) + mockCalleeAddr, false, 0, abi.encodeWithSignature("getBlockHash(uint256)", block.number) ); batchValue[1] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 0, - abi.encodeWithSignature("store(uint256)", type(uint256).max) + mockCalleeAddr, false, 0, abi.encodeWithSignature("store(uint256)", type(uint256).max) ); /** * @dev We don't allow for a failure. */ - batchValue[2] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 0, - abi.encodeWithSignature("thisMethodReverts()") - ); + batchValue[2] = IMulticall.BatchValue(mockCalleeAddr, false, 0, abi.encodeWithSignature("thisMethodReverts()")); batchValue[3] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 1, - abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) + mockCalleeAddr, false, 1, abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) ); - vm.expectRevert( - abi.encodeWithSelector(Reverted.selector, mockCalleeAddr) - ); + vm.expectRevert(abi.encodeWithSelector(Reverted.selector, mockCalleeAddr)); multicall.multicall_value{value: 1}(batchValue); } function testMulticallValueRevertCase2() public { - IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[]( - 4 - ); + IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[](4); batchValue[0] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 0, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) + mockCalleeAddr, false, 0, abi.encodeWithSignature("getBlockHash(uint256)", block.number) ); batchValue[1] = IMulticall.BatchValue( - mockCalleeAddr, - false, - 0, - abi.encodeWithSignature("store(uint256)", type(uint256).max) - ); - batchValue[2] = IMulticall.BatchValue( - mockCalleeAddr, - true, - 0, - abi.encodeWithSignature("thisMethodReverts()") + mockCalleeAddr, false, 0, abi.encodeWithSignature("store(uint256)", type(uint256).max) ); + batchValue[2] = IMulticall.BatchValue(mockCalleeAddr, true, 0, abi.encodeWithSignature("thisMethodReverts()")); batchValue[3] = IMulticall.BatchValue( - mockCalleeAddr, - true, - 1, - abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) + mockCalleeAddr, true, 1, abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) ); vm.expectRevert(bytes("Multicall: value mismatch")); @@ -204,50 +114,23 @@ contract MulticallTest is Test { function testMulticallSelfSuccess() public { IMulticall.Batch[] memory batch1 = new IMulticall.Batch[](3); - batch1[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch1[1] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("store(uint256)", type(uint256).max) - ); - batch1[2] = IMulticall.Batch( - mockCalleeAddr, - true, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch1[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch1[1] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); + batch1[2] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); IMulticall.Batch[] memory batch2 = new IMulticall.Batch[](2); - batch2[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch2[1] = IMulticall.Batch( - mockCalleeAddr, - true, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch2[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch2[1] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); IMulticall.BatchSelf[] memory batchSelf = new IMulticall.BatchSelf[](2); - batchSelf[0] = IMulticall.BatchSelf( - false, - abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1) - ); - batchSelf[1] = IMulticall.BatchSelf( - false, - abi.encodeWithSignature( - "multistaticcall((address,bool,bytes)[])", - batch2 - ) - ); + batchSelf[0] = IMulticall.BatchSelf(false, abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1)); + batchSelf[1] = + IMulticall.BatchSelf(false, abi.encodeWithSignature("multistaticcall((address,bool,bytes)[])", batch2)); - IMulticall.Result[] memory results = multicall.multicall_self( - batchSelf - ); + IMulticall.Result[] memory results = multicall.multicall_self(batchSelf); assertTrue(results[0].success); assertTrue(results[1].success); assertEq(mockCallee.number(), type(uint256).max); @@ -255,92 +138,44 @@ contract MulticallTest is Test { function testMulticallSelfRevert() public { IMulticall.Batch[] memory batch1 = new IMulticall.Batch[](3); - batch1[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch1[1] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("store(uint256)", type(uint256).max) - ); - batch1[2] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch1[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch1[1] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); + batch1[2] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("thisMethodReverts()")); IMulticall.Batch[] memory batch2 = new IMulticall.Batch[](2); - batch2[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch2[1] = IMulticall.Batch( - mockCalleeAddr, - true, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch2[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch2[1] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); IMulticall.BatchSelf[] memory batchSelf = new IMulticall.BatchSelf[](2); - batchSelf[0] = IMulticall.BatchSelf( - false, - abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1) - ); - batchSelf[1] = IMulticall.BatchSelf( - false, - abi.encodeWithSignature( - "multistaticcall((address,bool,bytes)[])", - batch2 - ) - ); + batchSelf[0] = IMulticall.BatchSelf(false, abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1)); + batchSelf[1] = + IMulticall.BatchSelf(false, abi.encodeWithSignature("multistaticcall((address,bool,bytes)[])", batch2)); - vm.expectRevert( - abi.encodeWithSelector(Reverted.selector, mockCalleeAddr) - ); + vm.expectRevert(abi.encodeWithSelector(Reverted.selector, mockCalleeAddr)); multicall.multicall_self(batchSelf); } function testMultistaticcallSuccess() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](2); - batch[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch[1] = IMulticall.Batch( - mockCalleeAddr, - true, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch[1] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); IMulticall.Result[] memory results = multicall.multistaticcall(batch); assertTrue(results[0].success); - assertEq( - keccak256(results[0].returnData), - keccak256(abi.encodePacked(blockhash(block.number))) - ); + assertEq(keccak256(results[0].returnData), keccak256(abi.encodePacked(blockhash(block.number)))); assertTrue(!results[1].success); } function testMultistaticcallRevert() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](3); - batch[0] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("getBlockHash(uint256)", block.number) - ); - batch[1] = IMulticall.Batch( - mockCalleeAddr, - false, - abi.encodeWithSignature("store(uint256)", type(uint256).max) - ); - batch[2] = IMulticall.Batch( - mockCalleeAddr, - true, - abi.encodeWithSignature("thisMethodReverts()") - ); + batch[0] = + IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); + batch[1] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); + batch[2] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); vm.expectRevert(); multicall.multistaticcall(batch); diff --git a/test/utils/SignatureChecker.t.sol b/test/utils/SignatureChecker.t.sol index 2f4bc67b..9ddc56ed 100644 --- a/test/utils/SignatureChecker.t.sol +++ b/test/utils/SignatureChecker.t.sol @@ -21,9 +21,7 @@ contract SignatureCheckerTest is Test { address private maliciousAddr = address(malicious); function setUp() public { - signatureChecker = ISignatureChecker( - vyperDeployer.deployContract("src/utils/", "SignatureChecker") - ); + signatureChecker = ISignatureChecker(vyperDeployer.deployContract("src/utils/", "SignatureChecker")); } function testEOAWithValidSignature() public { @@ -31,16 +29,8 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - signatureChecker.is_valid_signature_now(alice, hash, signature) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signature - ) - ); + assertTrue(signatureChecker.is_valid_signature_now(alice, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); } function testEOAWithInvalidSigner() public { @@ -48,16 +38,8 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key + 1, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now(alice, hash, signature) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); } function testEOAWithInvalidSignature1() public { @@ -66,20 +48,8 @@ contract SignatureCheckerTest is Test { bytes32 hashWrong = keccak256("WAGMI1"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hashWrong); bytes memory signatureInvalid = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now( - alice, - hash, - signatureInvalid - ) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signatureInvalid - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signatureInvalid)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signatureInvalid)); } function testEOAWithInvalidSignature2() public { @@ -89,35 +59,18 @@ contract SignatureCheckerTest is Test { bytes memory signatureInvalid = abi.encodePacked(r, s, bytes1(0xa0)); vm.expectRevert(bytes("ECDSA: invalid signature")); signatureChecker.is_valid_signature_now(alice, hash, signatureInvalid); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signatureInvalid - ) - ); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signatureInvalid)); } function testEOAWithTooHighSValue() public { (address alice, uint256 key) = makeAddrAndKey("alice"); bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); - uint256 sTooHigh = uint256(s) + - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; - bytes memory signatureInvalid = abi.encodePacked( - r, - bytes32(sTooHigh), - v - ); + uint256 sTooHigh = uint256(s) + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; + bytes memory signatureInvalid = abi.encodePacked(r, bytes32(sTooHigh), v); vm.expectRevert(bytes("ECDSA: invalid signature `s` value")); signatureChecker.is_valid_signature_now(alice, hash, signatureInvalid); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signatureInvalid - ) - ); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signatureInvalid)); } function testEIP1271WithValidSignature() public { @@ -125,16 +78,8 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - signatureChecker.is_valid_signature_now(walletAddr, hash, signature) - ); - assertTrue( - signatureChecker.is_valid_ERC1271_signature_now( - walletAddr, - hash, - signature - ) - ); + assertTrue(signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); + assertTrue(signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); } function testEIP1271WithInvalidSigner() public { @@ -142,20 +87,8 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key + 1, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now( - walletAddr, - hash, - signature - ) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - walletAddr, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); } function testEIP1271WithInvalidSignature1() public { @@ -164,20 +97,8 @@ contract SignatureCheckerTest is Test { bytes32 hashWrong = keccak256("WAGMI1"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hashWrong); bytes memory signatureInvalid = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now( - walletAddr, - hash, - signatureInvalid - ) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - walletAddr, - hash, - signatureInvalid - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signatureInvalid)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signatureInvalid)); } function testEIP1271WithInvalidSignature2() public { @@ -186,18 +107,8 @@ contract SignatureCheckerTest is Test { (, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signatureInvalid = abi.encodePacked(r, s, bytes1(0xa0)); vm.expectRevert(bytes("ECDSA: invalid signature")); - signatureChecker.is_valid_signature_now( - walletAddr, - hash, - signatureInvalid - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - walletAddr, - hash, - signatureInvalid - ) - ); + signatureChecker.is_valid_signature_now(walletAddr, hash, signatureInvalid); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signatureInvalid)); } function testEIP1271WithMaliciousWallet() public { @@ -205,20 +116,8 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now( - maliciousAddr, - hash, - signature - ) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - maliciousAddr, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(maliciousAddr, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(maliciousAddr, hash, signature)); } function testEIP1271NoIsValidSignatureFunction() public { @@ -226,75 +125,34 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now(deployer, hash, signature) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - deployer, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(deployer, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(deployer, hash, signature)); } - function testFuzzEOAWithValidSignature( - string calldata signer, - string calldata message - ) public { + function testFuzzEOAWithValidSignature(string calldata signer, string calldata message) public { (address alice, uint256 key) = makeAddrAndKey(signer); bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - signatureChecker.is_valid_signature_now(alice, hash, signature) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signature - ) - ); + assertTrue(signatureChecker.is_valid_signature_now(alice, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); } - function testFuzzEOAWithInvalidSigner( - string calldata signer, - string calldata message - ) public { + function testFuzzEOAWithInvalidSigner(string calldata signer, string calldata message) public { (address alice, uint256 key) = makeAddrAndKey(signer); bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key + 1, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now(alice, hash, signature) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); } - function testFuzzEOAWithInvalidSignature( - bytes calldata signature, - string calldata message - ) public { + function testFuzzEOAWithInvalidSignature(bytes calldata signature, string calldata message) public { vm.assume(signature.length < 64); address alice = makeAddr("alice"); bytes32 hash = keccak256(abi.encode(message)); - assertTrue( - !signatureChecker.is_valid_signature_now(alice, hash, signature) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - alice, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); } function testFuzzEIP1271WithValidSignature(string calldata message) public { @@ -302,64 +160,24 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - signatureChecker.is_valid_signature_now(walletAddr, hash, signature) - ); - assertTrue( - signatureChecker.is_valid_ERC1271_signature_now( - walletAddr, - hash, - signature - ) - ); + assertTrue(signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); + assertTrue(signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); } - function testFuzzEIP1271WithInvalidSigner( - string calldata signer, - string calldata message - ) public { - vm.assume( - keccak256(abi.encode(signer)) != keccak256(abi.encode("alice")) - ); + function testFuzzEIP1271WithInvalidSigner(string calldata signer, string calldata message) public { + vm.assume(keccak256(abi.encode(signer)) != keccak256(abi.encode("alice"))); (, uint256 key) = makeAddrAndKey(signer); bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue( - !signatureChecker.is_valid_signature_now( - walletAddr, - hash, - signature - ) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - walletAddr, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); } - function testEIP1271WithInvalidSignature( - bytes calldata signature, - string calldata message - ) public { + function testEIP1271WithInvalidSignature(bytes calldata signature, string calldata message) public { vm.assume(signature.length < 64); bytes32 hash = keccak256(abi.encode(message)); - assertTrue( - !signatureChecker.is_valid_signature_now( - walletAddr, - hash, - signature - ) - ); - assertTrue( - !signatureChecker.is_valid_ERC1271_signature_now( - walletAddr, - hash, - signature - ) - ); + assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); + assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); } } diff --git a/test/utils/interfaces/IBase64.sol b/test/utils/interfaces/IBase64.sol index 69f5c047..1184883d 100644 --- a/test/utils/interfaces/IBase64.sol +++ b/test/utils/interfaces/IBase64.sol @@ -2,13 +2,7 @@ pragma solidity ^0.8.23; interface IBase64 { - function encode( - bytes calldata data, - bool base64Url - ) external pure returns (string[] memory); + function encode(bytes calldata data, bool base64Url) external pure returns (string[] memory); - function decode( - string calldata data, - bool base64Url - ) external pure returns (bytes[] memory); + function decode(string calldata data, bool base64Url) external pure returns (bytes[] memory); } diff --git a/test/utils/interfaces/ICreate2Address.sol b/test/utils/interfaces/ICreate2Address.sol index ad829609..e12ff008 100644 --- a/test/utils/interfaces/ICreate2Address.sol +++ b/test/utils/interfaces/ICreate2Address.sol @@ -2,14 +2,7 @@ pragma solidity ^0.8.23; interface ICreate2Address { - function compute_address_self( - bytes32 salt, - bytes32 bytecodeHash - ) external view returns (address); + function compute_address_self(bytes32 salt, bytes32 bytecodeHash) external view returns (address); - function compute_address( - bytes32 salt, - bytes32 bytecodeHash, - address deployer - ) external view returns (address); + function compute_address(bytes32 salt, bytes32 bytecodeHash, address deployer) external view returns (address); } diff --git a/test/utils/interfaces/ICreateAddress.sol b/test/utils/interfaces/ICreateAddress.sol index dd002989..95303897 100644 --- a/test/utils/interfaces/ICreateAddress.sol +++ b/test/utils/interfaces/ICreateAddress.sol @@ -2,12 +2,7 @@ pragma solidity ^0.8.23; interface ICreateAddress { - function compute_address_rlp_self( - uint256 nonce - ) external view returns (address); + function compute_address_rlp_self(uint256 nonce) external view returns (address); - function compute_address_rlp( - address deployer, - uint256 nonce - ) external view returns (address); + function compute_address_rlp(address deployer, uint256 nonce) external view returns (address); } diff --git a/test/utils/interfaces/IECDSA.sol b/test/utils/interfaces/IECDSA.sol index b6588e43..062209b2 100644 --- a/test/utils/interfaces/IECDSA.sol +++ b/test/utils/interfaces/IECDSA.sol @@ -2,26 +2,16 @@ pragma solidity ^0.8.23; interface IECDSA { - function recover_sig( - bytes32 hash, - bytes calldata signature - ) external pure returns (address); + function recover_sig(bytes32 hash, bytes calldata signature) external pure returns (address); - function to_eth_signed_message_hash( - bytes32 hash - ) external pure returns (bytes32); + function to_eth_signed_message_hash(bytes32 hash) external pure returns (bytes32); - function to_typed_data_hash( - bytes32 domainSeparator, - bytes32 structHash - ) external pure returns (bytes32); + function to_typed_data_hash(bytes32 domainSeparator, bytes32 structHash) external pure returns (bytes32); - function to_data_with_intended_validator_hash_self( - bytes calldata data - ) external view returns (bytes32); + function to_data_with_intended_validator_hash_self(bytes calldata data) external view returns (bytes32); - function to_data_with_intended_validator_hash( - address validator, - bytes calldata data - ) external pure returns (bytes32); + function to_data_with_intended_validator_hash(address validator, bytes calldata data) + external + pure + returns (bytes32); } diff --git a/test/utils/interfaces/IEIP712DomainSeparator.sol b/test/utils/interfaces/IEIP712DomainSeparator.sol index cf2ffa0b..6867b5dc 100644 --- a/test/utils/interfaces/IEIP712DomainSeparator.sol +++ b/test/utils/interfaces/IEIP712DomainSeparator.sol @@ -6,7 +6,5 @@ import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; interface IEIP712DomainSeparator is IERC5267 { function domain_separator_v4() external view returns (bytes32); - function hash_typed_data_v4( - bytes32 structHash - ) external view returns (bytes32); + function hash_typed_data_v4(bytes32 structHash) external view returns (bytes32); } diff --git a/test/utils/interfaces/IMath.sol b/test/utils/interfaces/IMath.sol index 41a33c8c..0b7c7123 100644 --- a/test/utils/interfaces/IMath.sol +++ b/test/utils/interfaces/IMath.sol @@ -2,10 +2,7 @@ pragma solidity ^0.8.23; interface IMath { - function uint256_average( - uint256 x, - uint256 y - ) external pure returns (uint256); + function uint256_average(uint256 x, uint256 y) external pure returns (uint256); function int256_average(int256 x, int256 y) external pure returns (int256); @@ -13,12 +10,7 @@ interface IMath { function signum(int256 x) external pure returns (int256); - function mul_div( - uint256 x, - uint256 y, - uint256 denominator, - bool roundup - ) external pure returns (uint256); + function mul_div(uint256 x, uint256 y, uint256 denominator, bool roundup) external pure returns (uint256); function log_2(uint256 x, bool roundup) external pure returns (uint256); diff --git a/test/utils/interfaces/IMerkleProofVerification.sol b/test/utils/interfaces/IMerkleProofVerification.sol index b740cbbe..2f57fd8b 100644 --- a/test/utils/interfaces/IMerkleProofVerification.sol +++ b/test/utils/interfaces/IMerkleProofVerification.sol @@ -2,11 +2,7 @@ pragma solidity ^0.8.23; interface IMerkleProofVerification { - function verify( - bytes32[] calldata proof, - bytes32 root, - bytes32 leaf - ) external pure returns (bool); + function verify(bytes32[] calldata proof, bytes32 root, bytes32 leaf) external pure returns (bool); function multi_proof_verify( bytes32[] calldata proof, diff --git a/test/utils/interfaces/IMulticall.sol b/test/utils/interfaces/IMulticall.sol index 4afa886b..eb896cd3 100644 --- a/test/utils/interfaces/IMulticall.sol +++ b/test/utils/interfaces/IMulticall.sol @@ -25,19 +25,11 @@ interface IMulticall { bytes returnData; } - function multicall( - Batch[] calldata batch - ) external returns (Result[] memory results); + function multicall(Batch[] calldata batch) external returns (Result[] memory results); - function multicall_value( - BatchValue[] calldata batchValue - ) external payable returns (Result[] memory results); + function multicall_value(BatchValue[] calldata batchValue) external payable returns (Result[] memory results); - function multicall_self( - BatchSelf[] calldata batchSelf - ) external returns (Result[] memory results); + function multicall_self(BatchSelf[] calldata batchSelf) external returns (Result[] memory results); - function multistaticcall( - Batch[] calldata batch - ) external pure returns (Result[] memory results); + function multistaticcall(Batch[] calldata batch) external pure returns (Result[] memory results); } diff --git a/test/utils/interfaces/ISignatureChecker.sol b/test/utils/interfaces/ISignatureChecker.sol index 2386e53d..32f32e3d 100644 --- a/test/utils/interfaces/ISignatureChecker.sol +++ b/test/utils/interfaces/ISignatureChecker.sol @@ -2,15 +2,13 @@ pragma solidity ^0.8.23; interface ISignatureChecker { - function is_valid_signature_now( - address signer, - bytes32 hash, - bytes calldata signature - ) external view returns (bool); + function is_valid_signature_now(address signer, bytes32 hash, bytes calldata signature) + external + view + returns (bool); - function is_valid_ERC1271_signature_now( - address signer, - bytes32 hash, - bytes calldata signature - ) external view returns (bool); + function is_valid_ERC1271_signature_now(address signer, bytes32 hash, bytes calldata signature) + external + view + returns (bool); } diff --git a/test/utils/mocks/Create2Impl.sol b/test/utils/mocks/Create2Impl.sol index 3afdd15b..cb448f67 100644 --- a/test/utils/mocks/Create2Impl.sol +++ b/test/utils/mocks/Create2Impl.sol @@ -30,10 +30,7 @@ contract Create2Impl { * @param codeHash The 32-byte bytecode digest of the contract creation bytecode. * @return address The 20-byte address where a contract will be stored. */ - function computeAddress( - bytes32 salt, - bytes32 codeHash - ) public view returns (address) { + function computeAddress(bytes32 salt, bytes32 codeHash) public view returns (address) { return Create2.computeAddress(salt, codeHash); } @@ -46,11 +43,11 @@ contract Create2Impl { * @param deployer The 20-byte deployer address. * @return address The 20-byte address where a contract will be stored. */ - function computeAddressWithDeployer( - bytes32 salt, - bytes32 codeHash, - address deployer - ) public pure returns (address) { + function computeAddressWithDeployer(bytes32 salt, bytes32 codeHash, address deployer) + public + pure + returns (address) + { return Create2.computeAddress(salt, codeHash, deployer); } diff --git a/test/utils/mocks/ERC1271MaliciousMock.sol b/test/utils/mocks/ERC1271MaliciousMock.sol index c4a39baf..3c3aebd7 100644 --- a/test/utils/mocks/ERC1271MaliciousMock.sol +++ b/test/utils/mocks/ERC1271MaliciousMock.sol @@ -15,16 +15,10 @@ contract ERC1271MaliciousMock is IERC1271 { * @dev Returns a malicious 4-byte magic value. * @return bytes4 The malicious 4-byte magic value. */ - function isValidSignature( - bytes32, - bytes memory - ) public pure override returns (bytes4) { + function isValidSignature(bytes32, bytes memory) public pure override returns (bytes4) { // solhint-disable-next-line no-inline-assembly assembly { - mstore( - 0, - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - ) + mstore(0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) return(0, 32) } } diff --git a/test/utils/mocks/ERC1271WalletMock.sol b/test/utils/mocks/ERC1271WalletMock.sol index 433c8d2c..a3d5d118 100644 --- a/test/utils/mocks/ERC1271WalletMock.sol +++ b/test/utils/mocks/ERC1271WalletMock.sol @@ -21,13 +21,7 @@ contract ERC1271WalletMock is Ownable, IERC1271 { * @param signature The secp256k1 64/65-byte signature of `hash`. * @return bytes4 The 4-byte magic value. */ - function isValidSignature( - bytes32 hash, - bytes memory signature - ) public view override returns (bytes4) { - return - ECDSA.recover(hash, signature) == owner() - ? this.isValidSignature.selector - : bytes4(0); + function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4) { + return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0); } } diff --git a/test/utils/mocks/ERC20Mock.sol b/test/utils/mocks/ERC20Mock.sol index b7d91b4f..41384ef2 100644 --- a/test/utils/mocks/ERC20Mock.sol +++ b/test/utils/mocks/ERC20Mock.sol @@ -11,12 +11,10 @@ import {ERC20} from "openzeppelin/token/ERC20/ERC20.sol"; * @dev Allows to mock a simple ERC-20 implementation. */ contract ERC20Mock is ERC20 { - constructor( - string memory name_, - string memory symbol_, - address initialAccount_, - uint256 initialBalance_ - ) payable ERC20(name_, symbol_) { + constructor(string memory name_, string memory symbol_, address initialAccount_, uint256 initialBalance_) + payable + ERC20(name_, symbol_) + { _mint(initialAccount_, initialBalance_); } diff --git a/test/utils/mocks/MockCallee.sol b/test/utils/mocks/MockCallee.sol index 129883c7..e0bbabbc 100644 --- a/test/utils/mocks/MockCallee.sol +++ b/test/utils/mocks/MockCallee.sol @@ -33,9 +33,7 @@ contract MockCallee { * @param blockNumber The block number. * @return blockHash The 32-byte block hash. */ - function getBlockHash( - uint256 blockNumber - ) public view returns (bytes32 blockHash) { + function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { blockHash = blockhash(blockNumber); } @@ -52,7 +50,7 @@ contract MockCallee { */ function transferEther(address target) public payable { // solhint-disable-next-line avoid-low-level-calls - (bool ok, ) = target.call{value: msg.value}(""); + (bool ok,) = target.call{value: msg.value}(""); if (!ok) revert Reverted(self); } } From 0e52804d9d338c7cc8c805c536c9049398b4f39d Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Sun, 14 Jan 2024 21:45:40 +0100 Subject: [PATCH 04/46] =?UTF-8?q?=E2=9C=85=20TimelockController=20testing?= =?UTF-8?q?=20suite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/governance/TimelockController.vy | 83 ++++++-- test/governance/TimelockController.t.sol | 250 +++++++++++++++++++++++ 2 files changed, 314 insertions(+), 19 deletions(-) create mode 100644 test/governance/TimelockController.t.sol diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 503f731f..80d92759 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -176,47 +176,87 @@ def supportsInterface(interface_id: bytes4) -> bool: # TODO: Most helper funtions below are originally public, but Vyper doesn't support that. wat do? -@internal +@external @view def isOperation(id: bytes32) -> bool: - return self.getOperationState(id) != OperationState.Unset + return self._isOperation(id) @internal @view +def _isOperation(id: bytes32) -> bool: + return self._getOperationState(id) != OperationState.Unset + +@external +@view def isOperationPending(id: bytes32) -> bool: - state: OperationState = self.getOperationState(id) - return state == OperationState.Waiting or state == OperationState.Ready + return self._isOperationPending(id) @internal @view +def _isOperationPending(id: bytes32) -> bool: + state: OperationState = self._getOperationState(id) + return state == OperationState.Waiting or state == OperationState.Ready + +@external +@view def isOperationReady(id: bytes32) -> bool: - return self.getOperationState(id) == OperationState.Ready + return self._isOperationReady(id) @internal @view +def _isOperationReady(id: bytes32) -> bool: + return self._getOperationState(id) == OperationState.Ready + +@external +@view def isOperationDone(id: bytes32) -> bool: - return self.getOperationState(id) == OperationState.Done + return self._isOperationDone(id) @internal @view +def _isOperationDone(id: bytes32) -> bool: + return self._getOperationState(id) == OperationState.Done + +@external +@view def getTimestamp(id: bytes32) -> uint256: - return self._timestamps[id] + return self._getTimestamp(id) @internal +@view +def _getTimestamp(id: bytes32) -> uint256: + return self._timestamps[id] + +@external @pure def hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: + return self._hashOperation(target, x, data, predecessor, salt) + +@internal +@pure +def _hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: value: uint256 = x return keccak256(_abi_encode(target, value, data, predecessor, salt)) -@internal +@external @pure def hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: - return keccak256(_abi_encode(targets, values, payloads, predecessor, salt)) + return self._hashOperationBatch(targets, values, payloads, predecessor, salt) @internal +@pure +def _hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: + return keccak256(_abi_encode(targets, values, payloads, predecessor, salt)) + +@external @view def getOperationState(id: bytes32) -> OperationState: - timestamp: uint256 = self.getTimestamp(id) + return self._getOperationState(id) + +@internal +@view +def _getOperationState(id: bytes32) -> OperationState: + timestamp: uint256 = self._getTimestamp(id) if (timestamp == 0): return OperationState.Unset elif (timestamp == _DONE_TIMESTAMP): @@ -226,11 +266,16 @@ def getOperationState(id: bytes32) -> OperationState: else: return OperationState.Ready +@external +@view +def getMinDelay() -> uint256: + return self._minDelay + @external def schedule(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32, delay: uint256): self._check_role(PROPOSER_ROLE, msg.sender) value: uint256 = x - id: bytes32 = self.hashOperation(target, value, data, predecessor, salt) + id: bytes32 = self._hashOperation(target, value, data, predecessor, salt) self._schedule(id, delay) log CallScheduled(id, 0, target, value, data, predecessor, delay) if (salt != empty(bytes32)): @@ -240,7 +285,7 @@ def schedule(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32, delay: uint256): self._check_role(PROPOSER_ROLE, msg.sender) assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" - id: bytes32 = self.hashOperationBatch(targets, values, payloads, predecessor, salt) + id: bytes32 = self._hashOperationBatch(targets, values, payloads, predecessor, salt) self._schedule(id, delay) idx: uint256 = empty(uint256) for target in targets: @@ -253,14 +298,14 @@ def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128 @internal def _schedule(id: bytes32, delay: uint256): - assert not(self.isOperation(id)), "TimelockController: operation already scheduled" + assert not(self._isOperation(id)), "TimelockController: operation already scheduled" assert delay >= self._minDelay, "TimelockController: insufficient delay" self._timestamps[id] = block.timestamp + delay @external def cancel(id: bytes32): self._check_role(CANCELLER_ROLE, msg.sender) - assert self.isOperationPending(id), "TimelockController: operation cannot be cancelled" + assert self._isOperationPending(id), "TimelockController: operation cannot be cancelled" self._timestamps[id] = 0 log Cancelled(id) @@ -268,7 +313,7 @@ def cancel(id: bytes32): def execute(target: address, x: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32): self._onlyRoleOrOpenRole(EXECUTOR_ROLE) value: uint256 = x - id: bytes32 = self.hashOperation(target, value, payload, predecessor, salt) + id: bytes32 = self._hashOperation(target, value, payload, predecessor, salt) self._beforeCall(id, predecessor) self._execute(target, value, payload) @@ -279,7 +324,7 @@ def execute(target: address, x: uint256, payload: Bytes[1_024], predecessor: byt def executeBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32): self._onlyRoleOrOpenRole(EXECUTOR_ROLE) assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" - id: bytes32 = self.hashOperationBatch(targets, values, payloads, predecessor, salt) + id: bytes32 = self._hashOperationBatch(targets, values, payloads, predecessor, salt) self._beforeCall(id, predecessor) idx: uint256 = empty(uint256) @@ -302,12 +347,12 @@ def _execute(target: address, x: uint256, payload: Bytes[1_024]): @internal @view def _beforeCall(id: bytes32, predecessor: bytes32): - assert self.isOperationReady(id), "TimelockController: operation is not ready" - assert predecessor == empty(bytes32) or self.isOperationDone(predecessor), "TimelockController: predecessor operation is not done" + assert self._isOperationReady(id), "TimelockController: operation is not ready" + assert predecessor == empty(bytes32) or self._isOperationDone(predecessor), "TimelockController: predecessor operation is not done" @internal def _afterCall(id: bytes32): - assert self.isOperationReady(id), "TimelockController: operation is not ready" + assert self._isOperationReady(id), "TimelockController: operation is not ready" self._timestamps[id] = _DONE_TIMESTAMP @external diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol new file mode 100644 index 00000000..aac29980 --- /dev/null +++ b/test/governance/TimelockController.t.sol @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: WTFPL +pragma solidity ^0.8.23; + +import {Test} from "forge-std/Test.sol"; +import {VyperDeployer} from "utils/VyperDeployer.sol"; + +import {TimelockController} from "openzeppelin/governance/TimelockController.sol"; + +contract TimelockControllerTest is Test { + uint256 internal constant MIN_DELAY = 2 days; + uint256 internal constant DONE_TIMESTAMP = 1; + uint256 internal constant DELAY_ONE_MONTH = 31 days; + uint256 internal constant DELAY_TWO_DAYS = 48 hours; + + address private immutable ADMIN = address(this); + address private constant PROPOSER_ONE = address(0x1); + address private constant PROPOSER_TWO = address(0x2); + address private constant EXECUTOR_ONE = address(0x3); + address private constant EXECUTOR_TWO = address(0x4); + address private constant STRANGER = address(0x99); + + bytes32 internal constant NO_PREDECESSOR = bytes32(""); + bytes32 internal constant EMPTY_SALT = bytes32(""); + + address[2] private PROPOSERS; + address[2] private EXECUTORS; + + Call[] internal calls; + + Counter private counter; + + struct Call { + address target; + uint256 value; + bytes data; + } + + VyperDeployer private vyperDeployer = new VyperDeployer(); + + TimelockController private timelockController; + + address private deployer = address(vyperDeployer); + + function setUp() public { + PROPOSERS[0] = PROPOSER_ONE; + PROPOSERS[1] = PROPOSER_TWO; + + EXECUTORS[0] = EXECUTOR_ONE; + EXECUTORS[1] = EXECUTOR_TWO; + + address[] memory proposers = new address[](2); + proposers[0] = PROPOSER_ONE; + proposers[1] = PROPOSER_TWO; + + address[] memory executors = new address[](2); + executors[0] = EXECUTOR_ONE; + executors[1] = EXECUTOR_TWO; + + bytes memory args = abi.encode(MIN_DELAY, proposers, executors, ADMIN); + timelockController = + TimelockController(payable(vyperDeployer.deployContract("src/governance/", "TimelockController", args))); + + counter = new Counter(address(timelockController)); + + calls.push(Call({target: address(counter), value: 0, data: abi.encodeWithSelector(Counter.increment.selector)})); + calls.push( + Call({target: address(counter), value: 0, data: abi.encodeWithSelector(Counter.setNumber.selector, 10)}) + ); + } + + function checkRoleNotSetForAddresses(TimelockController timelock, bytes32 role, address[2] storage addresses) + internal + { + for (uint256 i = 0; i < addresses.length; ++i) { + assertFalse(timelock.hasRole(role, addresses[i])); + } + } + + function testInitialSetup() public { + assertEq(timelockController.hasRole(timelockController.DEFAULT_ADMIN_ROLE(), address(this)), true); + + checkRoleNotSetForAddresses(timelockController, timelockController.DEFAULT_ADMIN_ROLE(), PROPOSERS); + checkRoleNotSetForAddresses(timelockController, timelockController.DEFAULT_ADMIN_ROLE(), EXECUTORS); + + assertEq(timelockController.hasRole(timelockController.PROPOSER_ROLE(), PROPOSER_ONE), true); + assertEq(timelockController.hasRole(timelockController.PROPOSER_ROLE(), PROPOSER_TWO), true); + + assertFalse(timelockController.hasRole(timelockController.PROPOSER_ROLE(), ADMIN)); + + checkRoleNotSetForAddresses(timelockController, timelockController.PROPOSER_ROLE(), EXECUTORS); + + assertEq(timelockController.hasRole(timelockController.EXECUTOR_ROLE(), EXECUTOR_ONE), true); + assertEq(timelockController.hasRole(timelockController.EXECUTOR_ROLE(), EXECUTOR_TWO), true); + assertFalse(timelockController.hasRole(timelockController.EXECUTOR_ROLE(), ADMIN)); + checkRoleNotSetForAddresses(timelockController, timelockController.EXECUTOR_ROLE(), PROPOSERS); + assertEq(timelockController.getMinDelay(), MIN_DELAY); + + // TODO: Add event emit checks. + } + + function testHashesBatchedOperationsCorrectly() public { + address[] memory targets = new address[](2); + targets[0] = address(this); + targets[1] = address(this); + + uint256[] memory values = new uint256[](2); + values[0] = 0; + values[1] = 1; + + bytes[] memory payloads = new bytes[](2); + payloads[0] = abi.encodeWithSelector(this.testHashesBatchedOperationsCorrectly.selector); + payloads[1] = abi.encodeWithSelector(this.testHashesBatchedOperationsCorrectly.selector); + + bytes32 predecessor = NO_PREDECESSOR; + bytes32 salt = EMPTY_SALT; + + bytes32 hashedOperation = timelockController.hashOperationBatch(targets, values, payloads, predecessor, salt); + bytes32 expectedHash = keccak256(abi.encode(targets, values, payloads, predecessor, salt)); + assertEq(hashedOperation, expectedHash); + } + + event MinDelayChange(uint256 oldDuration, uint256 newDuration); + + function testRevertWhenNotAdminRole() public { + vm.expectRevert("TimelockController: unauthorized"); + vm.prank(STRANGER); + timelockController.updateDelay(3 days); + } + + function testUpdatesMinDelay() public { + address target = address(timelockController); + uint256 value = 0; + bytes memory data = abi.encodeWithSelector(timelockController.updateDelay.selector, MIN_DELAY); + + bytes32 predecessor = NO_PREDECESSOR; + bytes32 salt = EMPTY_SALT; + + vm.prank(PROPOSER_ONE); + timelockController.schedule(target, value, data, predecessor, salt, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + timelockController.execute(target, value, data, predecessor, salt); + + uint256 minDelay = timelockController.getMinDelay(); + assertEq(minDelay, 3 days); + } + + function testRevertWhenLessThanMinDelay() public { + address target = address(timelockController); + uint256 value = 0; + bytes memory data = abi.encodeWithSelector(timelockController.updateDelay.selector, 0); + + bytes32 predecessor = NO_PREDECESSOR; + bytes32 salt = EMPTY_SALT; + + vm.expectRevert("TimelockController: insufficient delay"); + vm.prank(PROPOSER_ONE); + timelockController.schedule(target, value, data, predecessor, salt, MIN_DELAY - 1); + } + + function testUpdatesDelayAtLeastMinDelay() public { + vm.prank(address(timelockController)); + timelockController.updateDelay(0); // set min delay to 0 + + address target = address(timelockController); + uint256 value = 0; + bytes memory data = abi.encodeWithSelector(timelockController.updateDelay.selector, MIN_DELAY); + + bytes32 predecessor = NO_PREDECESSOR; + bytes32 salt = EMPTY_SALT; + + vm.prank(PROPOSER_ONE); + timelockController.schedule(target, value, data, NO_PREDECESSOR, EMPTY_SALT, 1); + + vm.warp(block.timestamp + 1); + + vm.prank(EXECUTOR_ONE); + timelockController.execute(target, value, data, predecessor, salt); + + uint256 minDelay = timelockController.getMinDelay(); + assertEq(minDelay, MIN_DELAY); + } + + function testRevertWhenNotProposer() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + } + + function _scheduleBatchedOperation(address proposer) internal { + address[] memory targets = new address[](calls.length); + uint256[] memory values = new uint256[](calls.length); + bytes[] memory payloads = new bytes[](calls.length); + + for (uint256 i = 0; i < calls.length; ++i) { + targets[i] = calls[i].target; + values[i] = calls[i].value; + payloads[i] = calls[i].data; + } + + bytes32 batchedOperationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + assertEq(timelockController.isOperation(batchedOperationID), false); + + vm.prank(proposer); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + assertEq(timelockController.isOperation(batchedOperationID), true); + } + + function testProposerCanBatchSchedule() public { + _scheduleBatchedOperation(PROPOSER_ONE); + } + + function testAdminCanBatchSchedule() public { + _scheduleBatchedOperation(ADMIN); + } +} + +contract Counter { + address private timelock; + uint256 public number; + + constructor(address _timelock) { + timelock = _timelock; + } + + function setNumber(uint256 newNumber) public onlyTimelock { + number = newNumber; + } + + function increment() public onlyTimelock { + number++; + } + + function mockRevert() public pure { + revert("Transaction reverted"); + } + + modifier onlyTimelock() { + require(msg.sender == timelock, "Not timelock controller"); + _; + } +} From 25ae3323887cf2e6047d170b25cd92f159bf5001 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Sun, 14 Jan 2024 23:31:25 +0100 Subject: [PATCH 05/46] =?UTF-8?q?=E2=9C=85=20Add=20more=20unit=20tests=20f?= =?UTF-8?q?or=20TimelockController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 485 ++++++++++++++++++++++- 1 file changed, 479 insertions(+), 6 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index aac29980..e93df112 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -193,7 +193,10 @@ contract TimelockControllerTest is Test { timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); } - function _scheduleBatchedOperation(address proposer) internal { + function _scheduleBatchedOperation() + internal + returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) + { address[] memory targets = new address[](calls.length); uint256[] memory values = new uint256[](calls.length); bytes[] memory payloads = new bytes[](calls.length); @@ -203,23 +206,493 @@ contract TimelockControllerTest is Test { values[i] = calls[i].value; payloads[i] = calls[i].data; } + } + + function testProposerCanBatchSchedule() public { + (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleBatchedOperation(); bytes32 batchedOperationID = timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + assertEq(timelockController.isOperation(batchedOperationID), false); - vm.prank(proposer); + vm.prank(PROPOSER_ONE); timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); assertEq(timelockController.isOperation(batchedOperationID), true); } - function testProposerCanBatchSchedule() public { - _scheduleBatchedOperation(PROPOSER_ONE); + function testAdminCantBatchSchedule() public { + (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleBatchedOperation(); + + bytes32 batchedOperationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + assertEq(timelockController.isOperation(batchedOperationID), false); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + assertEq(timelockController.isOperation(batchedOperationID), false); + } + + function testRevertWhenScheduleIfOperationScheduled() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.startPrank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.expectRevert("TimelockController: operation already scheduled"); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + } + + function testRevertWhenScheduleIfDelayLessThanMinDelay() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.expectRevert("TimelockController: insufficient delay"); + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY - 1); + } + + function testProposerCanScheduleOperation() public { + bytes32 operationID = _scheduleOperation(PROPOSER_ONE); + assertTrue(timelockController.isOperation(operationID)); + } + + function testAdminCantScheduleOperation() public { + vm.expectRevert("AccessControl: account is missing role"); + bytes32 operationID = _scheduleOperation(ADMIN); + assertFalse(timelockController.isOperation(operationID)); + } + + function _scheduleOperation(address proposer) internal returns (bytes32 operationID) { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.startPrank(proposer); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + operationID = timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function _laterDelay() internal { + vm.prank(address(timelockController)); + timelockController.updateDelay(31 days); + } + + function testReturnsLaterMinDelayForCalls() public { + _laterDelay(); + uint256 minDelay = timelockController.getMinDelay(); + assertEq(minDelay, 31 days); + } + + function testRevertWhenLaterDelayTooLow() public { + _laterDelay(); + + address[] memory targets = new address[](calls.length); + uint256[] memory values = new uint256[](calls.length); + bytes[] memory payloads = new bytes[](calls.length); + + for (uint256 i = 0; i < calls.length; ++i) { + targets[i] = calls[i].target; + values[i] = calls[i].value; + payloads[i] = calls[i].data; + } + + vm.expectRevert("TimelockController: insufficient delay"); + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, 31 days - 1); + } + + function _scheduleBatchedOperation(address proposer, uint256 delay) internal { + address[] memory targets = new address[](calls.length); + uint256[] memory values = new uint256[](calls.length); + bytes[] memory payloads = new bytes[](calls.length); + + for (uint256 i = 0; i < calls.length; ++i) { + targets[i] = calls[i].target; + values[i] = calls[i].value; + payloads[i] = calls[i].data; + } + + bytes32 batchedOperationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + assertEq(timelockController.isOperation(batchedOperationID), false); + + vm.prank(proposer); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, delay); + + assertEq(timelockController.isOperation(batchedOperationID), true); + + uint256 operationTimestamp = timelockController.getTimestamp(batchedOperationID); + assertEq(operationTimestamp, block.timestamp + delay); + } + + function testProposerCanBatchScheduleGreaterEqualToLaterMinDelay() public { + _laterDelay(); + _scheduleBatchedOperation(PROPOSER_ONE, 31 days); + } + + function testUpdateDelayDoesNotChangeExistingOperationTimestamps() public { + _laterDelay(); + + address[] memory targets = new address[](calls.length); + uint256[] memory values = new uint256[](calls.length); + bytes[] memory payloads = new bytes[](calls.length); + + for (uint256 i = 0; i < calls.length; ++i) { + targets[i] = calls[i].target; + values[i] = calls[i].value; + payloads[i] = calls[i].data; + } + + bytes32 batchedOperationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, 31 days); + + uint256 operationTimestampBefore = timelockController.getTimestamp(batchedOperationID); + + // Set a new delay value + vm.prank(address(timelockController)); + timelockController.updateDelay(31 days + 1); + + // New delay value should only apply on future operations, not existing ones + uint256 operationTimestampAfter = timelockController.getTimestamp(batchedOperationID); + assertEq(operationTimestampAfter, operationTimestampBefore); + } + + function testRevertWhenNotExecutor() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); } - function testAdminCanBatchSchedule() public { - _scheduleBatchedOperation(ADMIN); + function testRevertWhenMultipleOperationNotReady() public { + address[] memory targets = new address[](calls.length); + uint256[] memory values = new uint256[](calls.length); + bytes[] memory payloads = new bytes[](calls.length); + + for (uint256 i = 0; i < calls.length; ++i) { + targets[i] = calls[i].target; + values[i] = calls[i].value; + payloads[i] = calls[i].data; + } + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY - 2 days); + + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function testRevertWhenPredecessorOperationNotExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.startPrank(PROPOSER_ONE); + + // Schedule predecessor job + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + bytes32 operationOneID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + // Schedule dependent job + timelockController.scheduleBatch(targets, values, payloads, operationOneID, EMPTY_SALT, MIN_DELAY); + vm.stopPrank(); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, operationOneID, EMPTY_SALT); + } + + function testRevertWhenPredecessorOperationNotScheduled() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.startPrank(PROPOSER_ONE); + + // Prepare predecessor job + bytes32 operationOneID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + // Schedule dependent job + timelockController.scheduleBatch(targets, values, payloads, operationOneID, EMPTY_SALT, MIN_DELAY); + vm.stopPrank(); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, operationOneID, EMPTY_SALT); + } + + function testRevertWhenPredecessorOperationInvalid() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // Prepare invalid predecessor + bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; + + // Schedule dependent job + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, invalidPredecessor, EMPTY_SALT, MIN_DELAY); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, invalidPredecessor, EMPTY_SALT); + } + + function testRevertWhenOneTargetReverts() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); + + // Schedule a job where one target will revert + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: underlying transaction reverted"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function testExecutorCanBatchExecuteOperation() public { + (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleSingleBatchedOperation(); + + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + uint256 operationTimestamp = timelockController.getTimestamp(operationID); + + assertEq(operationTimestamp, DONE_TIMESTAMP); + } + + function testAdminCantBatchExecuteOperation() public { + (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleSingleBatchedOperation(); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + uint256 operationTimestamp = timelockController.getTimestamp(operationID); + + assertEq(operationTimestamp, block.timestamp); + } + + function _scheduleSingleBatchedOperation() + internal + returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) + { + targets = new address[](1); + targets[0] = address(counter); + + values = new uint256[](1); + values[0] = 0; + + payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + + // Schedule batch executon + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY); + } + + function testRevertWhenExecutedByNonExecutor() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function testRevertWhenSingleOperationNotReady() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + vm.warp(block.timestamp + MIN_DELAY - 2 days); + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function testRevertWhenPredecessorMultipleOperationNotExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // Schedule predecessor job + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + bytes32 operationOneID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); + + // Schedule dependent job + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, operationOneID, EMPTY_SALT, MIN_DELAY); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, operationOneID, EMPTY_SALT); + } + + function testRevertWhenTargetReverts() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); + + vm.prank(PROPOSER_ONE); + + // Schedule predecessor job + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: underlying transaction reverted"); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function testExecutorCanExecuteOperation() public { + uint256 num = 10; + (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _executeOperation(num); + + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + uint256 operationTimestamp = timelockController.getTimestamp(operationID); + assertEq(operationTimestamp, DONE_TIMESTAMP); + uint256 counterNumber = counter.number(); + assertEq(counterNumber, num); + } + + function testAdminCantExecuteOperation() public { + uint256 num = 10; + (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _executeOperation(num); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + uint256 operationTimestamp = timelockController.getTimestamp(operationID); + assertEq(operationTimestamp, block.timestamp - MIN_DELAY); + uint256 counterNumber = counter.number(); + assertEq(counterNumber, 0); + } + + function _executeOperation(uint256 num) + internal + returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) + { + targets = new address[](1); + targets[0] = address(counter); + + values = new uint256[](1); + values[0] = 0; + + payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, num); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY + 2 days); } } From 4517efb88ebbb21f317b432ac93b3a6852f99378 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Mon, 15 Jan 2024 00:00:24 +0100 Subject: [PATCH 06/46] =?UTF-8?q?=E2=9C=85=20Add=20remaining=20unit=20test?= =?UTF-8?q?s=20for=20TimelockController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 341 ++++++++++++++++++++++- 1 file changed, 340 insertions(+), 1 deletion(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index e93df112..f933015b 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -144,7 +144,7 @@ contract TimelockControllerTest is Test { timelockController.execute(target, value, data, predecessor, salt); uint256 minDelay = timelockController.getMinDelay(); - assertEq(minDelay, 3 days); + assertEq(minDelay, 2 days); } function testRevertWhenLessThanMinDelay() public { @@ -694,6 +694,345 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY + 2 days); } + + event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data); + + function testEmitsEvent() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + bytes32 predecessor = NO_PREDECESSOR; + bytes32 salt = EMPTY_SALT; + bytes32 id = timelockController.hashOperationBatch(targets, values, payloads, predecessor, salt); + + vm.prank(EXECUTOR_ONE); + vm.expectEmit(true, true, true, true); + emit CallExecuted(id, 0, targets[0], values[0], payloads[0]); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function testRevertWhenNonCanceller() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_ONE); + timelockController.cancel(EMPTY_SALT); + } + + function testRevertWhenFinishedOperation() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY + 1); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + vm.prank(PROPOSER_ONE); + vm.expectRevert("TimelockController: operation cannot be cancelled"); + timelockController.cancel(operationID); + } + + function testCancellerCanCancelOperation() public { + (bytes32 operationID) = _cancelOperation(); + + vm.prank(PROPOSER_ONE); + timelockController.cancel(operationID); + assertFalse(timelockController.isOperation(operationID)); + } + + function testAdminCanCancelOperation() public { + (bytes32 operationID) = _cancelOperation(); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.cancel(operationID); + assertTrue(timelockController.isOperation(operationID)); + } + + function _cancelOperation() internal returns (bytes32 operationID) { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + operationID = timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + } + + function testCanReceiveETH() public { + vm.prank(ADMIN); + payable(address(timelockController)).transfer(0.5 ether); + assertEq(address(timelockController).balance, 0.5 ether); + } + + function testFalseIfNotAnOperation() public { + bool isOperation = timelockController.isOperation(bytes32("non-op")); + assertEq(isOperation, false); + } + + function testTrueIfAnOperation() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperation = timelockController.isOperation(operationID); + assertEq(isOperation, true); + } + + function testTrueIfScheduledOperatonNotYetExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationPending = timelockController.isOperationPending(operationID); + assertEq(isOperationPending, true); + } + + function testFalseIfPendingOperationHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationPending = timelockController.isOperationPending(operationID); + assertEq(isOperationPending, false); + } + + function testTrueIfOnTheDelayedExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationReady = timelockController.isOperationReady(operationID); + assertEq(isOperationReady, true); + } + + function testTrueIfAfterTheDelayedExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY + 1 days); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationReady = timelockController.isOperationReady(operationID); + assertEq(isOperationReady, true); + } + + function testFalseIfBeforeTheDelayedExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY - 1 days); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationReady = timelockController.isOperationReady(operationID); + assertEq(isOperationReady, false); + } + + function testFalseIfReadyOperationHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationReady = timelockController.isOperationReady(operationID); + assertEq(isOperationReady, false); + } + + function testFalseItTheOperationHasNotBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationDone = timelockController.isOperationDone(operationID); + assertEq(isOperationDone, false); + } + + function testTrueIfOperationHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bool isOperationDone = timelockController.isOperationDone(operationID); + assertEq(isOperationDone, true); + } + + function testReturnsTheCorrectTimestampIfTheOperationHasNotBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + uint256 operationTimestamp = timelockController.getTimestamp(operationID); + assertEq(operationTimestamp, block.timestamp + MIN_DELAY); + } + + function testReturnsOneIfOperationHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.prank(PROPOSER_ONE); + timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + bytes32 operationID = + timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + + uint256 operationTimestamp = timelockController.getTimestamp(operationID); + assertEq(operationTimestamp, DONE_TIMESTAMP); + } } contract Counter { From 1f15e08bff59f7ba06860be1ec4d4095e2af803a Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Mon, 15 Jan 2024 01:19:54 +0100 Subject: [PATCH 07/46] =?UTF-8?q?=F0=9F=9A=A7=20TimelockController=20invar?= =?UTF-8?q?iant=20setup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index f933015b..498632a5 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -1060,3 +1060,49 @@ contract Counter { _; } } + +contract TimelockControllerInvariants is Test { + VyperDeployer private vyperDeployer = new VyperDeployer(); + + TimelockController private timelockController; + TimelockControllerHandler private timelockControllerHandler; + + address private deployer = address(vyperDeployer); + + function setUp() public { + address[] memory proposers = new address[](2); + proposers[0] = PROPOSER_ONE; + proposers[1] = PROPOSER_TWO; + + address[] memory executors = new address[](2); + executors[0] = EXECUTOR_ONE; + executors[1] = EXECUTOR_TWO; + + bytes memory args = abi.encode(MIN_DELAY, proposers, executors, ADMIN); + timelockController = + TimelockController(payable(vyperDeployer.deployContract("src/governance/", "TimelockController", args))); + + timelockControllerHandler = new AccessControlHandler(timelockController); + targetContract(address(timelockControllerHandler)); + } +} + +contract TimelockControllerHandler { + TimelockController private timelockController; + + constructor( + TimelockController timelockController_, + address defaultAdmin_, + bytes32 adminRole_, + bytes32 additionalRole1_, + bytes32 additionalRole2_ + ) { + timelockController = timelockController_; + } + + function schedule() public {} + + function execute() public {} + + function cancel() public {} +} From ee311129bc37ec17656cd0377a912794d311ef4a Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Tue, 16 Jan 2024 02:05:31 +0100 Subject: [PATCH 08/46] =?UTF-8?q?=F0=9F=9A=A7=20Add=20invariant=20template?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 90 +++++++++++++++++++----- 1 file changed, 74 insertions(+), 16 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 498632a5..a9689d96 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -1070,39 +1070,97 @@ contract TimelockControllerInvariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - address[] memory proposers = new address[](2); - proposers[0] = PROPOSER_ONE; - proposers[1] = PROPOSER_TWO; + address[] memory proposers = new address[](1); + proposers[0] = address(this); - address[] memory executors = new address[](2); - executors[0] = EXECUTOR_ONE; - executors[1] = EXECUTOR_TWO; + address[] memory executors = new address[](1); + executors[0] = address(this); - bytes memory args = abi.encode(MIN_DELAY, proposers, executors, ADMIN); + uint256 minDelay = 2 days; + + bytes memory args = abi.encode(minDelay, proposers, executors, address(this)); timelockController = TimelockController(payable(vyperDeployer.deployContract("src/governance/", "TimelockController", args))); - timelockControllerHandler = new AccessControlHandler(timelockController); + timelockControllerHandler = + new TimelockControllerHandler(timelockController, minDelay, proposers, executors, address(this)); targetContract(address(timelockControllerHandler)); } + + // Proposals can only be scheduled and executed once + function invariantOnceProposalExecution() public {} + + // Executed proposals cannot be cancelled + function invariantExecutedProposalCancellation() public {} + + // Executing a proposal twice is not possible + function invariantExecutingProposalTwice() public {} + + // Executing a proposal that has been cancelled is not possible + function invariantExecutingCancelledProposal() public {} + + // Executing a proposal that is not ready is not possible + function invariantExecutingNotReadyProposal() public {} + + // Executing a proposal that is not scheduled is not possible + function invariantExecutingNotScheduledProposal() public {} } -contract TimelockControllerHandler { +contract TimelockControllerHandler is Test { TimelockController private timelockController; + uint256 private minDelay; + address private admin; + address private proposer; + address private executor; + + uint256 public counter; + + uint256 public schedule_count; + uint256 public execute_count; + uint256 public cancel_count; + + mapping(bytes32 => bool) public operations; + + bytes32[] public operationIDs; constructor( TimelockController timelockController_, - address defaultAdmin_, - bytes32 adminRole_, - bytes32 additionalRole1_, - bytes32 additionalRole2_ + uint256 minDelay_, + address[] memory proposer_, + address[] memory executor_, + address admin_ ) { timelockController = timelockController_; + minDelay = minDelay_; + proposer = proposer_[0]; + executor = executor_[0]; + admin = admin_; } - function schedule() public {} + function schedule(uint256 random) external { + vm.prank(proposer); + timelockController.schedule( + address(this), + 0, + abi.encodeWithSelector(this.increment.selector), + bytes32(random), + bytes32(random), + minDelay + ); - function execute() public {} + bytes32 operationID = timelockController.hashOperation( + address(this), 0, abi.encodeWithSelector(this.increment.selector), bytes32(random), bytes32(random) + ); + + operationIDs.push(operationID); + schedule_count++; + } - function cancel() public {} + function execute() external {} + + function cancel() external {} + + function increment() external { + counter++; + } } From 0623b05829631554cd073b1c719cf78bfa3f6cbf Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:10:01 +0100 Subject: [PATCH 09/46] =?UTF-8?q?=E2=9C=85=20Add=20invariant=20tests=20for?= =?UTF-8?q?=20TimelockController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 117 +++++++++++++++++++---- 1 file changed, 97 insertions(+), 20 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index a9689d96..e420bbe6 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -1084,17 +1084,65 @@ contract TimelockControllerInvariants is Test { timelockControllerHandler = new TimelockControllerHandler(timelockController, minDelay, proposers, executors, address(this)); + + // Select the selectors to use for fuzzing. + bytes4[] memory selectors = new bytes4[](3); + selectors[0] = TimelockControllerHandler.schedule.selector; + selectors[1] = TimelockControllerHandler.execute.selector; + selectors[2] = TimelockControllerHandler.cancel.selector; + + // Set the target selector. + targetSelector(FuzzSelector({addr: address(timelockControllerHandler), selectors: selectors})); + + // Set the target contract. targetContract(address(timelockControllerHandler)); } + // Number of pending transactions cannot exceed executed transactions + function invariantExecutedLessThanOrEqualToPending() public { + assertLe(timelockControllerHandler.execute_count(), timelockControllerHandler.schedule_count()); + } + + // Number of proposals executed must match the count number). + function invariantOnceProposalExecution() public { + assertEq(timelockControllerHandler.execute_count(), timelockControllerHandler.counter()); + } + // Proposals can only be scheduled and executed once - function invariantOnceProposalExecution() public {} + function invariantOnceProposalExecution2() public { + uint256[] memory executed = timelockControllerHandler.getExecuted(); + // Loop over all executed proposals. + for (uint256 i = 0; i < executed.length; ++i) { + // Check that the executed proposal cannot be executed again. + vm.expectRevert("TimelockController: operation is not ready"); + timelockController.execute( + address(timelockControllerHandler), + 0, + abi.encodeWithSelector(TimelockControllerHandler.increment.selector), + bytes32(""), + bytes32(executed[i]) + ); + } + } - // Executed proposals cannot be cancelled - function invariantExecutedProposalCancellation() public {} + // Sum of number of executed proposals and cancelled proposals must match the amount of proposals scheduled. + function invariantExecutedProposalCancellation() public { + assertEq( + timelockControllerHandler.cancel_count() + timelockControllerHandler.execute_count(), + timelockControllerHandler.schedule_count() + ); + } - // Executing a proposal twice is not possible - function invariantExecutingProposalTwice() public {} + // Executed proposals cannot be cancelled + function invariantExecutedProposalCancellation2() public { + uint256[] memory executed = timelockControllerHandler.getExecuted(); + // Loop over all executed proposals. + for (uint256 i = 0; i < executed.length; ++i) { + // Check that the executed proposal cannot be cancelled. + vm.expectRevert("TimelockController: operation cannot be cancelled"); + timelockController.cancel(bytes32(executed[i])); + } + } // Executing a proposal that has been cancelled is not possible function invariantExecutingCancelledProposal() public {} @@ -1119,9 +1167,9 @@ contract TimelockControllerHandler is Test { uint256 public execute_count; uint256 public cancel_count; - mapping(bytes32 => bool) public operations; - - bytes32[] public operationIDs; + uint256[] public pending; + uint256[] public executed; + uint256[] public cancelled; constructor( TimelockController timelockController_, @@ -1140,25 +1188,54 @@ contract TimelockControllerHandler is Test { function schedule(uint256 random) external { vm.prank(proposer); timelockController.schedule( - address(this), - 0, - abi.encodeWithSelector(this.increment.selector), - bytes32(random), - bytes32(random), - minDelay + address(this), 0, abi.encodeWithSelector(this.increment.selector), bytes32(""), bytes32(random), minDelay ); - bytes32 operationID = timelockController.hashOperation( - address(this), 0, abi.encodeWithSelector(this.increment.selector), bytes32(random), bytes32(random) + pending.push(random); + schedule_count++; + + vm.warp(block.timestamp + minDelay); + } + + function execute(uint256 random) external { + if (pending.length == 0) { + return; + } + + uint256 identifier = random % pending.length; + uint256 operation = pending[identifier]; + + vm.prank(executor); + timelockController.execute( + address(this), 0, abi.encodeWithSelector(this.increment.selector), bytes32(""), bytes32(operation) ); - operationIDs.push(operationID); - schedule_count++; + delete pending[identifier]; + executed.push(operation); + + execute_count++; } - function execute() external {} + function cancel(uint256 random) external { + if (pending.length == 0) { + return; + } + + uint256 identifier = random % pending.length; + uint256 operation = pending[identifier]; + + vm.prank(proposer); + timelockController.cancel(bytes32(operation)); - function cancel() external {} + delete pending[identifier]; + cancelled.push(operation); + + cancel_count++; + } + + function getExecuted() external view returns (uint256[] memory) { + return executed; + } function increment() external { counter++; From c48e0c6cf66332e492eecde3962f6ff7e3d71061 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:17:25 +0100 Subject: [PATCH 10/46] =?UTF-8?q?=E2=9C=85=20Wrap=20up=20invariant=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 74 +++++++++++++++++------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index e420bbe6..ce89704a 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -194,12 +194,12 @@ contract TimelockControllerTest is Test { } function _scheduleBatchedOperation() - internal + internal view returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) { - address[] memory targets = new address[](calls.length); - uint256[] memory values = new uint256[](calls.length); - bytes[] memory payloads = new bytes[](calls.length); + targets = new address[](calls.length); + values = new uint256[](calls.length); + payloads = new bytes[](calls.length); for (uint256 i = 0; i < calls.length; ++i) { targets[i] = calls[i].target; @@ -1103,13 +1103,13 @@ contract TimelockControllerInvariants is Test { assertLe(timelockControllerHandler.execute_count(), timelockControllerHandler.schedule_count()); } - // Number of proposals executed must match the count number). - function invariantOnceProposalExecution() public { + // Number of proposals executed must match the count number. + function invariantProposalsExecutedMatchCount() public { assertEq(timelockControllerHandler.execute_count(), timelockControllerHandler.counter()); } // Proposals can only be scheduled and executed once - function invariantOnceProposalExecution2() public { + function invariantOnceProposalExecution() public { uint256[] memory executed = timelockControllerHandler.getExecuted(); // Loop over all executed proposals. for (uint256 i = 0; i < executed.length; ++i) { @@ -1125,16 +1125,16 @@ contract TimelockControllerInvariants is Test { } } - // Sum of number of executed proposals and cancelled proposals must match the amount of proposals scheduled. - function invariantExecutedProposalCancellation() public { - assertEq( + // Sum of number of executed proposals and cancelled proposals must be less or equal to the amount of proposals scheduled. + function invariantSumOfProposals() public { + assertLe( timelockControllerHandler.cancel_count() + timelockControllerHandler.execute_count(), timelockControllerHandler.schedule_count() ); } // Executed proposals cannot be cancelled - function invariantExecutedProposalCancellation2() public { + function invariantExecutedProposalCancellation() public { uint256[] memory executed = timelockControllerHandler.getExecuted(); // Loop over all executed proposals. for (uint256 i = 0; i < executed.length; ++i) { @@ -1145,13 +1145,38 @@ contract TimelockControllerInvariants is Test { } // Executing a proposal that has been cancelled is not possible - function invariantExecutingCancelledProposal() public {} + function invariantExecutingCancelledProposal() public { + uint256[] memory cancelled = timelockControllerHandler.getCancelled(); + // Loop over all cancelled proposals. + for (uint256 i = 0; i < cancelled.length; ++i) { + // Check that the cancelled proposal cannot be executed. + vm.expectRevert("TimelockController: operation is not ready"); + timelockController.execute( + address(timelockControllerHandler), + 0, + abi.encodeWithSelector(TimelockControllerHandler.increment.selector), + bytes32(""), + bytes32(cancelled[i]) + ); + } + } // Executing a proposal that is not ready is not possible - function invariantExecutingNotReadyProposal() public {} - - // Executing a proposal that is not scheduled is not possible - function invariantExecutingNotScheduledProposal() public {} + function invariantExecutingNotReadyProposal() public { + uint256[] memory pending = timelockControllerHandler.getPending(); + // Loop over all pending proposals. + for (uint256 i = 0; i < pending.length; ++i) { + // Check that the pending proposal cannot be executed. + vm.expectRevert("TimelockController: operation is not ready"); + timelockController.execute( + address(timelockControllerHandler), + 0, + abi.encodeWithSelector(TimelockControllerHandler.increment.selector), + bytes32(""), + bytes32(pending[i]) + ); + } + } } contract TimelockControllerHandler is Test { @@ -1193,18 +1218,19 @@ contract TimelockControllerHandler is Test { pending.push(random); schedule_count++; - - vm.warp(block.timestamp + minDelay); } function execute(uint256 random) external { - if (pending.length == 0) { + if (pending.length == 0 || schedule_count == 0) { return; } uint256 identifier = random % pending.length; uint256 operation = pending[identifier]; + // Advance time to make the proposal ready. + vm.warp(block.timestamp + minDelay); + vm.prank(executor); timelockController.execute( address(this), 0, abi.encodeWithSelector(this.increment.selector), bytes32(""), bytes32(operation) @@ -1217,7 +1243,7 @@ contract TimelockControllerHandler is Test { } function cancel(uint256 random) external { - if (pending.length == 0) { + if (pending.length == 0 || schedule_count == 0) { return; } @@ -1237,6 +1263,14 @@ contract TimelockControllerHandler is Test { return executed; } + function getCancelled() external view returns (uint256[] memory) { + return cancelled; + } + + function getPending() external view returns (uint256[] memory) { + return pending; + } + function increment() external { counter++; } From d9f758fd1e5b73aeec1993442e1463cae5db8eed Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Wed, 17 Jan 2024 01:07:12 +0100 Subject: [PATCH 11/46] =?UTF-8?q?=F0=9F=92=A1=20Update=20format=20and=20ad?= =?UTF-8?q?d=20comments/natspec?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/governance/TimelockController.vy | 412 +++++++++++++++++++++-- test/governance/TimelockController.t.sol | 3 +- 2 files changed, 393 insertions(+), 22 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 80d92759..fab3acdf 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -1,4 +1,34 @@ # pragma version ^0.3.10 +""" +@title Owner-Based Timelock Controller +@custom:contract-name TimelockController +@license GNU Affero General Public License v3.0 only +@author cairoeth +@notice This module allows for timelocking operations by scheduling and + executing transactions. By leveraging AccessControl, the + TimelockController introduces three roles: proposer, executor, + and canceller. The proposer role is responsible for proposing + operations, the executor is responsible for executing scheduled + proposals, and the canceller is responsible for cancelling + proposals. The owner is the sole admin of the roles and can grant + and revoke them. In the constructor, proposers will be granted + the proposer and canceller roles. + + Proposals must be scheduled with a delay that is greater than or + equal to the minimum delay (`minDelay()`), which can be updated via + a proposal to itself and is measured in seconds. Additionally, + proposals can be associated with preceding proposals, which must be + executed before the proposal can be executed. Ready proposals can be + executed by the executor, who is solely responsible for calling the + `execute()` function. + + Proposals can be timelocked individually or in batches. The latter is + useful for operations that require execution in the same block. + + The implementation is inspired by OpenZeppelin's implementation here: + https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/TimelockController.sol. +""" + # @dev We import and implement the `ERC165` interface, # which is a built-in interface of the Vyper compiler. @@ -86,24 +116,50 @@ event RoleRevoked: account: indexed(address) sender: indexed(address) + +# @dev Proposer 32-byte role. +# @notice Responsable for proposing operations. PROPOSER_ROLE: public(constant(bytes32)) = keccak256("PROPOSER_ROLE") + +# @dev Executor 32-byte role. +# @notice Responsable for executing scheduled +# proposals. EXECUTOR_ROLE: public(constant(bytes32)) = keccak256("EXECUTOR_ROLE") + +# @dev Canceller 32-byte role. +# @notice Responsable for cancelling proposals. CANCELLER_ROLE: public(constant(bytes32)) = keccak256("CANCELLER_ROLE") + +# @dev The timestamp that represents that a +# proposal has been executed. _DONE_TIMESTAMP: constant(uint256) = 1 + +# @dev The mapping of proposal IDs to their +# timestamps. _timestamps: HashMap[bytes32, uint256] + +# @dev The minimum delay required to schedule a +# proposal. _minDelay: uint256 + +# @dev The possible statuses of a proposal. enum OperationState: Unset Waiting Ready Done + +# @dev Emitted when a call is scheduled as part +# of operation `id`. Note that the `index` is the +# index position of the proposal. If the proposal +# is individual, the `index` is 0. event CallScheduled: id: indexed(bytes32) index: indexed(uint256) @@ -113,6 +169,11 @@ event CallScheduled: predecessor: bytes32 delay: uint256 + +# @dev Emitted when a call is performed as part +# of operation `id`. Note that the `index` is +# the index position of the proposal. If the +# proposal is individual, the `index` is 0. event CallExecuted: id: indexed(bytes32) index: indexed(uint256) @@ -120,19 +181,40 @@ event CallExecuted: value: uint256 data: Bytes[1_024] + +# @dev Emitted when new proposal is scheduled +# with non-zero salt. event CallSalt: id: indexed(bytes32) salt: bytes32 + +# @dev Emitted when operation `id` is cancelled. event Cancelled: id: indexed(bytes32) + +# @dev Emitted when the minimum delay for future +# operations is modified. event MinDelayChange: oldDuration: uint256 newDuration: uint256 + @external def __init__(minDelay: uint256, proposers: DynArray[address, 128], executors: DynArray[address, 128], admin: address): + """ + @dev The optional admin can aid with initial + configuration of roles after deployment without + being subject to delay, but this role should be + subsequently renounced in favor of + administration through timelocked proposals. + Previous versions of this contract would assign + this admin to the deployer automatically and + should be renounced as well. + @notice Assigns roles to given addresses and sets the + minimum delay. + """ # Self administration self._grant_role(DEFAULT_ADMIN_ROLE, self) @@ -152,16 +234,31 @@ def __init__(minDelay: uint256, proposers: DynArray[address, 128], executors: Dy self._minDelay = minDelay log MinDelayChange(0, minDelay) + @external @payable def __default__(): + """ + @dev Contract might receive/hold ETH as part of the + maintenance process. + """ pass + @internal def _onlyRoleOrOpenRole(role: bytes32): + """ + @dev Used to limit a function to be callable only by + a certain role. In addition to checking the + sender's role, `empty(address)` is also + considered. Granting a role to `empty(address)` + is equivalent to enabling this role for everyone. + @param role The 32-byte role definition. + """ if (not(self.hasRole[role][empty(address)])): self._check_role(role, msg.sender) + @external @view def supportsInterface(interface_id: bytes4) -> bool: @@ -174,88 +271,159 @@ def supportsInterface(interface_id: bytes4) -> bool: """ return interface_id in _SUPPORTED_INTERFACES -# TODO: Most helper funtions below are originally public, but Vyper doesn't support that. wat do? @external @view def isOperation(id: bytes32) -> bool: + """ + @dev Returns whether an id corresponds to a registered + operation. This includes both Waiting, Ready, and + Done operations. + @param id The 32-byte operation identifier. + @return bool The verification whether the id + corresponds to a registered operation or not. + """ return self._isOperation(id) + @internal @view def _isOperation(id: bytes32) -> bool: + """ + @dev Internal logic of `isOperation`. + @param id The 32-byte operation identifier. + @return bool The verification whether the id + corresponds to a registered operation or not. + """ return self._getOperationState(id) != OperationState.Unset + @external @view def isOperationPending(id: bytes32) -> bool: + """ + @dev Returns whether an operation is pending or not. + Note that a "pending" operation may also be + "ready". + @param id The 32-byte operation identifier. + @return bool The verification whether the operation + is pending or not. + """ return self._isOperationPending(id) + @internal @view def _isOperationPending(id: bytes32) -> bool: + """ + @dev Internal logic of `isOperationPending`. + @param id The 32-byte operation identifier. + @return bool The verification whether the operation + is pending or not. + """ state: OperationState = self._getOperationState(id) return state == OperationState.Waiting or state == OperationState.Ready + @external @view def isOperationReady(id: bytes32) -> bool: + """ + @dev Returns whether an operation is ready + for execution. Note that a "ready" + operation is also "pending". + @param id The 32-byte operation identifier. + @return bool The verification whether + the operation is ready or not. + """ return self._isOperationReady(id) + @internal @view def _isOperationReady(id: bytes32) -> bool: + """ + @dev Internal logic of `_isOperationReady`. + @param id The 32-byte operation identifier. + @return bool The verification whether + the operation is ready or not. + """ return self._getOperationState(id) == OperationState.Ready + @external @view def isOperationDone(id: bytes32) -> bool: + """ + @dev Returns whether an operation is done + or not. + @param id The 32-byte operation identifier. + @return bool The verification whether + the operation is done or not. + """ return self._isOperationDone(id) + @internal @view def _isOperationDone(id: bytes32) -> bool: + """ + @dev Internal logic of `_isOperationDone`. + @param id The 32-byte operation identifier. + @return bool The verification whether + the operation is done or not. + """ return self._getOperationState(id) == OperationState.Done + @external @view def getTimestamp(id: bytes32) -> uint256: + """ + @dev Returns the timestamp at which an + operation becomes ready (0 for + unset operations, 1 for done + operations). + @param id The 32-byte operation identifier. + @return uint256 The timestamp at which + the operation becomes ready. + """ return self._getTimestamp(id) + @internal @view def _getTimestamp(id: bytes32) -> uint256: + """ + @dev Internal logic of `_getTimestamp`. + @param id The 32-byte operation identifier. + @return uint256 The timestamp at which + the operation becomes ready. + """ return self._timestamps[id] -@external -@pure -def hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: - return self._hashOperation(target, x, data, predecessor, salt) - -@internal -@pure -def _hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: - value: uint256 = x - return keccak256(_abi_encode(target, value, data, predecessor, salt)) - -@external -@pure -def hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: - return self._hashOperationBatch(targets, values, payloads, predecessor, salt) - -@internal -@pure -def _hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: - return keccak256(_abi_encode(targets, values, payloads, predecessor, salt)) @external @view def getOperationState(id: bytes32) -> OperationState: + """ + @dev Returns the state of an operation. + @param id The 32-byte operation identifier. + @return OperationState The state of the + operation. + """ return self._getOperationState(id) + @internal @view def _getOperationState(id: bytes32) -> OperationState: + """ + @dev Internal logic of `_getOperationState`. + @param id The 32-byte operation identifier. + @return OperationState The state of the + operation. + """ timestamp: uint256 = self._getTimestamp(id) if (timestamp == 0): return OperationState.Unset @@ -266,13 +434,111 @@ def _getOperationState(id: bytes32) -> OperationState: else: return OperationState.Ready + @external @view def getMinDelay() -> uint256: + """ + @dev Returns the minimum delay in seconds + for an operation to become valid. + This value can be changed by executing + an operation that calls `updateDelay`. + @return uint256 The minimum delay required + to schedule a proposal. + """ return self._minDelay + +@external +@pure +def hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: + """ + @dev Returns the identifier of an operation + containing a single transaction. + @param target The address of the target contract. + @param x The amount of native token to send + with the call. + @param data The ABI-encoded call data. + @param predecessor The hash of the preceding + operation (optional with empty bytes). + @param salt The salt of the operation. + @return bytes32 The hash of the operation. + """ + return self._hashOperation(target, x, data, predecessor, salt) + + +@internal +@pure +def _hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: + """ + @dev Internal logic of `hashOperation`. + @param target The address of the target contract. + @param x The amount of native token to send + with the call. + @param data The ABI-encoded call data. + @param predecessor The hash of the preceding + operation (optional with empty bytes). + @param salt The salt of the operation. + @return bytes32 The hash of the operation. + """ + value: uint256 = x + return keccak256(_abi_encode(target, value, data, predecessor, salt)) + + +@external +@pure +def hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: + """ + @dev Returns the identifier of an operation + containing a batch of transactions. + @param targets The address of the targets contract. + @param values The amounts of native token to send + with each call. + @param payloads The ABI-encoded calls data. + @param predecessor The hash of the preceding + operation (optional with empty bytes). + @param salt The salt of the operation. + @return bytes32 The hash of the operation. + """ + return self._hashOperationBatch(targets, values, payloads, predecessor, salt) + + +@internal +@pure +def _hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: + """ + @dev Internal logic of `hashOperationBatch`. + @param targets The address of the targets contract. + @param values The amounts of native token to send + with each call. + @param payloads The ABI-encoded calls data. + @param predecessor The hash of the preceding + operation (optional with empty bytes). + @param salt The salt of the operation. + @return bytes32 The hash of the operation. + """ + return keccak256(_abi_encode(targets, values, payloads, predecessor, salt)) + + @external def schedule(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32, delay: uint256): + """ + @dev Schedule an operation containing a single + transaction. Emits `CallSalt` if salt is + nonzero, and `CallScheduled`. + @param target The address of the target contract. + @param x The amount of native token to send + with the call. + @param data The ABI-encoded call data. + @param predecessor The hash of the preceding + operation. + @param salt The salt of the operation. + @param delay The delay before the operation + becomes valid. Must be greater than or + equal to the minimum delay. + @notice Requires the caller to have the + `proposer` role. + """ self._check_role(PROPOSER_ROLE, msg.sender) value: uint256 = x id: bytes32 = self._hashOperation(target, value, data, predecessor, salt) @@ -281,8 +547,27 @@ def schedule(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes if (salt != empty(bytes32)): log CallSalt(id, salt) + @external def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32, delay: uint256): + """ + @dev Schedule an operation containing a batch + of transactions. Emits `CallSalt` if salt + is nonzero, and one `CallScheduled` event + per transaction in the batch. + @param targets The address of the target contracts. + @param values The amounts of native token to send + with the call. + @param payloads The ABI-encoded calls data. + @param predecessor The hash of the preceding + operation. + @param salt The salt of the operation. + @param delay The delay before the operation + becomes valid. Must be greater than or + equal to the minimum delay. + @notice Requires the caller to have the + `proposer` role. + """ self._check_role(PROPOSER_ROLE, msg.sender) assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" id: bytes32 = self._hashOperationBatch(targets, values, payloads, predecessor, salt) @@ -296,21 +581,55 @@ def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128 if (salt != empty(bytes32)): log CallSalt(id, salt) + @internal def _schedule(id: bytes32, delay: uint256): + """ + @dev Schedule an operation that is to become + valid after a given delay. + @param id The 32-byte operation identifier. + @param delay The delay before the operation + becomes valid. Must be greater than or + equal to the minimum delay. + """ assert not(self._isOperation(id)), "TimelockController: operation already scheduled" assert delay >= self._minDelay, "TimelockController: insufficient delay" self._timestamps[id] = block.timestamp + delay + @external def cancel(id: bytes32): + """ + @dev Cancel an operation. + @notice Requires the caller to have the + `canceller` role. + @param id The 32-byte operation identifier. + """ self._check_role(CANCELLER_ROLE, msg.sender) assert self._isOperationPending(id), "TimelockController: operation cannot be cancelled" self._timestamps[id] = 0 log Cancelled(id) + @external def execute(target: address, x: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32): + """ + @dev Execute an (ready) operation + containing a single transaction. + Emits a `CallExecuted` event. + @param target The address of the target contract. + @param x The amount of native token to send + with the call. + @param payload The ABI-encoded call data. + @param predecessor The hash of the preceding + operation. + @param salt The salt of the operation. + @notice Requires the caller to have the `executor` role. + This function can reenter, but it doesn't pose + a risk because `_afterCall` checks that the + proposal is pending, thus any modifications to + the operation during reentrancy should be caught. + """ self._onlyRoleOrOpenRole(EXECUTOR_ROLE) value: uint256 = x id: bytes32 = self._hashOperation(target, value, payload, predecessor, salt) @@ -320,8 +639,27 @@ def execute(target: address, x: uint256, payload: Bytes[1_024], predecessor: byt log CallExecuted(id, 0, target, value, payload) self._afterCall(id) + @external def executeBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32): + """ + @dev Execute an (ready) operation + containing a batch of transactions. + Emits one `CallExecuted` event per + transaction in the batch. + @param targets The address of the target contracts. + @param values The amounts of native token to send + with the call. + @param payloads The ABI-encoded calls data. + @param predecessor The hash of the preceding + operation. + @param salt The salt of the operation. + @notice Requires the caller to have the `executor` role. + This function can reenter, but it doesn't pose + a risk because `_afterCall` checks that the + proposal is pending, thus any modifications to + the operation during reentrancy should be caught. + """ self._onlyRoleOrOpenRole(EXECUTOR_ROLE) assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" id: bytes32 = self._hashOperationBatch(targets, values, payloads, predecessor, salt) @@ -336,31 +674,63 @@ def executeBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128] idx = unsafe_add(idx, 1) self._afterCall(id) + @internal def _execute(target: address, x: uint256, payload: Bytes[1_024]): + """ + @dev Execute an operation's call. + @param target The address of the target contract. + @param x The amount of native token to send + with the call. + @param payload The ABI-encoded call data. + """ value: uint256 = x return_data: Bytes[max_value(uint8)] = b"" success: bool = empty(bool) success, return_data = raw_call(target, payload, max_outsize=255, revert_on_failure=False) assert success, "TimelockController: underlying transaction reverted" + @internal @view def _beforeCall(id: bytes32, predecessor: bytes32): + """ + @dev Checks before execution of an operation's calls. + @param id The 32-byte operation identifier. + @param predecessor The hash of the preceding + operation. + """ assert self._isOperationReady(id), "TimelockController: operation is not ready" assert predecessor == empty(bytes32) or self._isOperationDone(predecessor), "TimelockController: predecessor operation is not done" + @internal def _afterCall(id: bytes32): + """ + @dev Checks after execution of an operation's calls. + @param id The 32-byte operation identifier. + """ assert self._isOperationReady(id), "TimelockController: operation is not ready" self._timestamps[id] = _DONE_TIMESTAMP + @external def updateDelay(newDelay: uint256): + """ + @dev Changes the minimum timelock duration for future + operations. Emits a `MinDelayChange` event. + @param newDelay The new minimum delay in seconds. + @notice Requires the caller to be the timelock itself. + This can only be achieved by scheduling and + later executing an operation where the timelock + is the target and the data is the ABI-encoded + call to this function. + """ assert msg.sender == self, "TimelockController: unauthorized" log MinDelayChange(self._minDelay, newDelay) self._minDelay = newDelay + @external def grantRole(role: bytes32, account: address): """ diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index ce89704a..d3292d39 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -194,7 +194,8 @@ contract TimelockControllerTest is Test { } function _scheduleBatchedOperation() - internal view + internal + view returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) { targets = new address[](calls.length); From b6ba7ea5ce9d5eb26b363edc86d85e59706543d4 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Thu, 18 Jan 2024 15:52:47 +0100 Subject: [PATCH 12/46] =?UTF-8?q?=F0=9F=92=84=20Prettify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/auth/AccessControl.t.sol | 175 ++- test/auth/Ownable.t.sol | 22 +- test/auth/Ownable2Step.t.sol | 42 +- test/auth/interfaces/IOwnable.sol | 5 +- test/auth/interfaces/IOwnable2Step.sol | 10 +- test/extensions/ERC2981.t.sol | 260 +++- test/extensions/ERC4626.t.sol | 1377 ++++++++++++++--- .../interfaces/IERC2981Extended.sol | 16 +- .../interfaces/IERC4626Extended.sol | 7 +- test/governance/TimelockController.t.sol | 1127 +++++++++++--- test/tokens/ERC1155.t.sol | 1215 ++++++++++++--- test/tokens/ERC20.t.sol | 326 +++- test/tokens/ERC721.t.sol | 745 +++++++-- test/tokens/interfaces/IERC1155Extended.sol | 28 +- test/tokens/interfaces/IERC20Extended.sol | 5 +- test/tokens/interfaces/IERC4494.sol | 9 +- test/tokens/interfaces/IERC721Extended.sol | 13 +- test/tokens/mocks/ERC1155ReceiverMock.sol | 34 +- test/tokens/mocks/ERC721ReceiverMock.sol | 11 +- test/utils/Base64.t.sol | 36 +- test/utils/BatchDistributor.t.sol | 293 +++- test/utils/Create2Address.t.sol | 102 +- test/utils/CreateAddress.t.sol | 716 +++++++-- test/utils/ECDSA.t.sol | 126 +- test/utils/EIP712DomainSeparator.t.sol | 103 +- test/utils/Math.t.sol | 101 +- test/utils/MerkleProofVerification.t.sol | 318 +++- test/utils/Multicall.t.sol | 291 +++- test/utils/SignatureChecker.t.sol | 264 +++- test/utils/interfaces/IBase64.sol | 10 +- test/utils/interfaces/ICreate2Address.sol | 11 +- test/utils/interfaces/ICreateAddress.sol | 9 +- test/utils/interfaces/IECDSA.sol | 26 +- .../interfaces/IEIP712DomainSeparator.sol | 4 +- test/utils/interfaces/IMath.sol | 12 +- .../interfaces/IMerkleProofVerification.sol | 6 +- test/utils/interfaces/IMulticall.sol | 16 +- test/utils/interfaces/ISignatureChecker.sol | 18 +- test/utils/mocks/Create2Impl.sol | 15 +- test/utils/mocks/ERC1271MaliciousMock.sol | 10 +- test/utils/mocks/ERC1271WalletMock.sol | 10 +- test/utils/mocks/ERC20Mock.sol | 10 +- test/utils/mocks/MockCallee.sol | 6 +- 43 files changed, 6476 insertions(+), 1464 deletions(-) diff --git a/test/auth/AccessControl.t.sol b/test/auth/AccessControl.t.sol index 937d8b85..43eae8ab 100644 --- a/test/auth/AccessControl.t.sol +++ b/test/auth/AccessControl.t.sol @@ -22,7 +22,9 @@ contract AccessControlTest is Test { address private deployer = address(vyperDeployer); function setUp() public { - accessControl = IAccessControlExtended(vyperDeployer.deployContract("src/auth/", "AccessControl")); + accessControl = IAccessControlExtended( + vyperDeployer.deployContract("src/auth/", "AccessControl") + ); } function testInitialSetup() public { @@ -32,9 +34,18 @@ contract AccessControlTest is Test { assertTrue(accessControl.hasRole(DEFAULT_ADMIN_ROLE, deployer)); assertTrue(accessControl.hasRole(ADDITIONAL_ROLE_1, deployer)); assertTrue(accessControl.hasRole(ADDITIONAL_ROLE_2, deployer)); - assertEq(accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), DEFAULT_ADMIN_ROLE); - assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), DEFAULT_ADMIN_ROLE); - assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), DEFAULT_ADMIN_ROLE); + assertEq( + accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), + DEFAULT_ADMIN_ROLE + ); + assertEq( + accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), + DEFAULT_ADMIN_ROLE + ); + assertEq( + accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), + DEFAULT_ADMIN_ROLE + ); vm.expectEmit(true, true, true, false); emit IAccessControl.RoleGranted(DEFAULT_ADMIN_ROLE, deployer, deployer); @@ -42,28 +53,59 @@ contract AccessControlTest is Test { emit IAccessControl.RoleGranted(ADDITIONAL_ROLE_1, deployer, deployer); vm.expectEmit(true, true, true, false); emit IAccessControl.RoleGranted(ADDITIONAL_ROLE_2, deployer, deployer); - accessControlInitialEvent = IAccessControlExtended(vyperDeployer.deployContract("src/auth/", "AccessControl")); - assertEq(accessControlInitialEvent.DEFAULT_ADMIN_ROLE(), DEFAULT_ADMIN_ROLE); - assertEq(accessControlInitialEvent.ADDITIONAL_ROLE_1(), ADDITIONAL_ROLE_1); - assertEq(accessControlInitialEvent.ADDITIONAL_ROLE_2(), ADDITIONAL_ROLE_2); - assertTrue(accessControlInitialEvent.hasRole(DEFAULT_ADMIN_ROLE, deployer)); - assertTrue(accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_1, deployer)); - assertTrue(accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_2, deployer)); - assertEq(accessControlInitialEvent.getRoleAdmin(DEFAULT_ADMIN_ROLE), DEFAULT_ADMIN_ROLE); - assertEq(accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_1), DEFAULT_ADMIN_ROLE); - assertEq(accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_2), DEFAULT_ADMIN_ROLE); + accessControlInitialEvent = IAccessControlExtended( + vyperDeployer.deployContract("src/auth/", "AccessControl") + ); + assertEq( + accessControlInitialEvent.DEFAULT_ADMIN_ROLE(), + DEFAULT_ADMIN_ROLE + ); + assertEq( + accessControlInitialEvent.ADDITIONAL_ROLE_1(), + ADDITIONAL_ROLE_1 + ); + assertEq( + accessControlInitialEvent.ADDITIONAL_ROLE_2(), + ADDITIONAL_ROLE_2 + ); + assertTrue( + accessControlInitialEvent.hasRole(DEFAULT_ADMIN_ROLE, deployer) + ); + assertTrue( + accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_1, deployer) + ); + assertTrue( + accessControlInitialEvent.hasRole(ADDITIONAL_ROLE_2, deployer) + ); + assertEq( + accessControlInitialEvent.getRoleAdmin(DEFAULT_ADMIN_ROLE), + DEFAULT_ADMIN_ROLE + ); + assertEq( + accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_1), + DEFAULT_ADMIN_ROLE + ); + assertEq( + accessControlInitialEvent.getRoleAdmin(ADDITIONAL_ROLE_2), + DEFAULT_ADMIN_ROLE + ); } function testSupportsInterfaceSuccess() public { assertTrue(accessControl.supportsInterface(type(IERC165).interfaceId)); - assertTrue(accessControl.supportsInterface(type(IAccessControl).interfaceId)); + assertTrue( + accessControl.supportsInterface(type(IAccessControl).interfaceId) + ); } function testSupportsInterfaceSuccessGasCost() public { uint256 startGas = gasleft(); accessControl.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && accessControl.supportsInterface(type(IERC165).interfaceId)); + assertTrue( + gasUsed <= 30_000 && + accessControl.supportsInterface(type(IERC165).interfaceId) + ); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -74,7 +116,9 @@ contract AccessControlTest is Test { uint256 startGas = gasleft(); accessControl.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && !accessControl.supportsInterface(0x0011bbff)); + assertTrue( + gasUsed <= 30_000 && !accessControl.supportsInterface(0x0011bbff) + ); } function testGrantRoleSuccess() public { @@ -247,7 +291,9 @@ contract AccessControlTest is Test { } function testRenounceRoleNonMsgSender() public { - vm.expectRevert(bytes("AccessControl: can only renounce roles for itself")); + vm.expectRevert( + bytes("AccessControl: can only renounce roles for itself") + ); accessControl.renounceRole(ADDITIONAL_ROLE_1, makeAddr("account")); } @@ -258,7 +304,11 @@ contract AccessControlTest is Test { bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); + emit IAccessControl.RoleAdminChanged( + ADDITIONAL_ROLE_1, + DEFAULT_ADMIN_ROLE, + otherAdminRole + ); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -288,7 +338,11 @@ contract AccessControlTest is Test { bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); + emit IAccessControl.RoleAdminChanged( + ADDITIONAL_ROLE_1, + DEFAULT_ADMIN_ROLE, + otherAdminRole + ); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -310,7 +364,11 @@ contract AccessControlTest is Test { accessControl.grantRole(ADDITIONAL_ROLE_1, account); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); + emit IAccessControl.RoleAdminChanged( + ADDITIONAL_ROLE_1, + DEFAULT_ADMIN_ROLE, + otherAdminRole + ); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -362,7 +420,10 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzGrantRoleNonAdmin(address nonAdmin, address account) public { + function testFuzzGrantRoleNonAdmin( + address nonAdmin, + address account + ) public { vm.assume(nonAdmin != deployer); vm.prank(nonAdmin); vm.expectRevert(bytes("AccessControl: account is missing role")); @@ -411,7 +472,10 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzRevokeRoleNonAdmin(address nonAdmin, address account) public { + function testFuzzRevokeRoleNonAdmin( + address nonAdmin, + address account + ) public { vm.assume(nonAdmin != deployer); vm.prank(nonAdmin); vm.expectRevert(bytes("AccessControl: account is missing role")); @@ -470,17 +534,26 @@ contract AccessControlTest is Test { function testFuzzRenounceRoleNonMsgSender(address account) public { vm.assume(address(this) != account); - vm.expectRevert(bytes("AccessControl: can only renounce roles for itself")); + vm.expectRevert( + bytes("AccessControl: can only renounce roles for itself") + ); accessControl.renounceRole(ADDITIONAL_ROLE_1, account); } - function testFuzzSetRoleAdminSuccess(address otherAdmin, address account) public { + function testFuzzSetRoleAdminSuccess( + address otherAdmin, + address account + ) public { vm.assume(otherAdmin != deployer && account != deployer); address admin = deployer; bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); + emit IAccessControl.RoleAdminChanged( + ADDITIONAL_ROLE_1, + DEFAULT_ADMIN_ROLE, + otherAdminRole + ); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -503,13 +576,20 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzSetRoleAdminPreviousAdminCallsGrantRole(address otherAdmin, address account) public { + function testFuzzSetRoleAdminPreviousAdminCallsGrantRole( + address otherAdmin, + address account + ) public { vm.assume(otherAdmin != deployer); address admin = deployer; bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); vm.startPrank(admin); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); + emit IAccessControl.RoleAdminChanged( + ADDITIONAL_ROLE_1, + DEFAULT_ADMIN_ROLE, + otherAdminRole + ); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -522,7 +602,10 @@ contract AccessControlTest is Test { vm.stopPrank(); } - function testFuzzSetRoleAdminPreviousAdminCallsRevokeRole(address otherAdmin, address account) public { + function testFuzzSetRoleAdminPreviousAdminCallsRevokeRole( + address otherAdmin, + address account + ) public { vm.assume(otherAdmin != deployer); address admin = deployer; bytes32 otherAdminRole = keccak256("OTHER_ADMIN_ROLE"); @@ -530,7 +613,11 @@ contract AccessControlTest is Test { accessControl.grantRole(ADDITIONAL_ROLE_1, account); vm.expectEmit(true, true, true, false); - emit IAccessControl.RoleAdminChanged(ADDITIONAL_ROLE_1, DEFAULT_ADMIN_ROLE, otherAdminRole); + emit IAccessControl.RoleAdminChanged( + ADDITIONAL_ROLE_1, + DEFAULT_ADMIN_ROLE, + otherAdminRole + ); accessControl.set_role_admin(ADDITIONAL_ROLE_1, otherAdminRole); vm.expectEmit(true, true, true, false); @@ -557,9 +644,16 @@ contract AccessControlInvariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - accessControl = IAccessControlExtended(vyperDeployer.deployContract("src/auth/", "AccessControl")); - accessControlHandler = - new AccessControlHandler(accessControl, deployer, DEFAULT_ADMIN_ROLE, ADDITIONAL_ROLE_1, ADDITIONAL_ROLE_2); + accessControl = IAccessControlExtended( + vyperDeployer.deployContract("src/auth/", "AccessControl") + ); + accessControlHandler = new AccessControlHandler( + accessControl, + deployer, + DEFAULT_ADMIN_ROLE, + ADDITIONAL_ROLE_1, + ADDITIONAL_ROLE_2 + ); targetContract(address(accessControlHandler)); } @@ -579,9 +673,18 @@ contract AccessControlInvariants is Test { } function invariantGetRoleAdmin() public { - assertEq(accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), accessControlHandler.getRoleAdmin(DEFAULT_ADMIN_ROLE)); - assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_1)); - assertEq(accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_2)); + assertEq( + accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), + accessControlHandler.getRoleAdmin(DEFAULT_ADMIN_ROLE) + ); + assertEq( + accessControl.getRoleAdmin(ADDITIONAL_ROLE_1), + accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_1) + ); + assertEq( + accessControl.getRoleAdmin(ADDITIONAL_ROLE_2), + accessControlHandler.getRoleAdmin(ADDITIONAL_ROLE_2) + ); } } diff --git a/test/auth/Ownable.t.sol b/test/auth/Ownable.t.sol index 5249157b..6e74b347 100644 --- a/test/auth/Ownable.t.sol +++ b/test/auth/Ownable.t.sol @@ -16,7 +16,9 @@ contract OwnableTest is Test { address private zeroAddress = address(0); function setUp() public { - ownable = IOwnable(vyperDeployer.deployContract("src/auth/", "Ownable")); + ownable = IOwnable( + vyperDeployer.deployContract("src/auth/", "Ownable") + ); } function testInitialSetup() public { @@ -24,7 +26,9 @@ contract OwnableTest is Test { vm.expectEmit(true, true, false, false); emit IOwnable.OwnershipTransferred(zeroAddress, deployer); - ownableInitialEvent = IOwnable(vyperDeployer.deployContract("src/auth/", "Ownable")); + ownableInitialEvent = IOwnable( + vyperDeployer.deployContract("src/auth/", "Ownable") + ); assertEq(ownableInitialEvent.owner(), deployer); } @@ -70,7 +74,10 @@ contract OwnableTest is Test { ownable.renounce_ownership(); } - function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { + function testFuzzTransferOwnershipSuccess( + address newOwner1, + address newOwner2 + ) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -88,7 +95,10 @@ contract OwnableTest is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { + function testFuzzTransferOwnershipNonOwner( + address nonOwner, + address newOwner + ) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -131,7 +141,9 @@ contract OwnableInvariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - ownable = IOwnable(vyperDeployer.deployContract("src/auth/", "Ownable")); + ownable = IOwnable( + vyperDeployer.deployContract("src/auth/", "Ownable") + ); ownerHandler = new OwnerHandler(ownable, deployer); targetContract(address(ownerHandler)); } diff --git a/test/auth/Ownable2Step.t.sol b/test/auth/Ownable2Step.t.sol index 77a4ef4a..e26d0ed7 100644 --- a/test/auth/Ownable2Step.t.sol +++ b/test/auth/Ownable2Step.t.sol @@ -16,7 +16,9 @@ contract Ownable2StepTest is Test { address private zeroAddress = address(0); function setUp() public { - ownable2Step = IOwnable2Step(vyperDeployer.deployContract("src/auth/", "Ownable2Step")); + ownable2Step = IOwnable2Step( + vyperDeployer.deployContract("src/auth/", "Ownable2Step") + ); } function testInitialSetup() public { @@ -25,7 +27,9 @@ contract Ownable2StepTest is Test { vm.expectEmit(true, true, false, false); emit IOwnable2Step.OwnershipTransferred(zeroAddress, deployer); - ownable2StepInitialEvent = IOwnable2Step(vyperDeployer.deployContract("src/auth/", "Ownable2Step")); + ownable2StepInitialEvent = IOwnable2Step( + vyperDeployer.deployContract("src/auth/", "Ownable2Step") + ); assertEq(ownable2StepInitialEvent.owner(), deployer); assertEq(ownable2StepInitialEvent.pending_owner(), zeroAddress); } @@ -126,7 +130,10 @@ contract Ownable2StepTest is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { + function testFuzzTransferOwnershipSuccess( + address newOwner1, + address newOwner2 + ) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -145,14 +152,20 @@ contract Ownable2StepTest is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { + function testFuzzTransferOwnershipNonOwner( + address nonOwner, + address newOwner + ) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable2Step: caller is not the owner")); ownable2Step.transfer_ownership(newOwner); } - function testFuzzAcceptOwnershipSuccess(address newOwner1, address newOwner2) public { + function testFuzzAcceptOwnershipSuccess( + address newOwner1, + address newOwner2 + ) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -236,7 +249,9 @@ contract Ownable2StepTest is Test { ownable2Step.renounce_ownership(); } - function testFuzzPendingOwnerResetAfterRenounceOwnership(address newOwner) public { + function testFuzzPendingOwnerResetAfterRenounceOwnership( + address newOwner + ) public { vm.assume(newOwner != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -269,8 +284,14 @@ contract Ownable2StepInvariants is Test { address private zeroAddress = address(0); function setUp() public { - ownable2Step = IOwnable2Step(vyperDeployer.deployContract("src/auth/", "Ownable2Step")); - owner2StepHandler = new Owner2StepHandler(ownable2Step, deployer, zeroAddress); + ownable2Step = IOwnable2Step( + vyperDeployer.deployContract("src/auth/", "Ownable2Step") + ); + owner2StepHandler = new Owner2StepHandler( + ownable2Step, + deployer, + zeroAddress + ); targetContract(address(owner2StepHandler)); } @@ -279,7 +300,10 @@ contract Ownable2StepInvariants is Test { } function invariantPendingOwner() public { - assertEq(ownable2Step.pending_owner(), owner2StepHandler.pending_owner()); + assertEq( + ownable2Step.pending_owner(), + owner2StepHandler.pending_owner() + ); } } diff --git a/test/auth/interfaces/IOwnable.sol b/test/auth/interfaces/IOwnable.sol index 8f1b015a..629dbcb2 100644 --- a/test/auth/interfaces/IOwnable.sol +++ b/test/auth/interfaces/IOwnable.sol @@ -2,7 +2,10 @@ pragma solidity ^0.8.23; interface IOwnable { - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); function owner() external view returns (address); diff --git a/test/auth/interfaces/IOwnable2Step.sol b/test/auth/interfaces/IOwnable2Step.sol index 7054c607..18c98f85 100644 --- a/test/auth/interfaces/IOwnable2Step.sol +++ b/test/auth/interfaces/IOwnable2Step.sol @@ -2,9 +2,15 @@ pragma solidity ^0.8.23; interface IOwnable2Step { - event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); + event OwnershipTransferStarted( + address indexed previousOwner, + address indexed newOwner + ); - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); function owner() external view returns (address); diff --git a/test/extensions/ERC2981.t.sol b/test/extensions/ERC2981.t.sol index e302026c..9327b1bf 100644 --- a/test/extensions/ERC2981.t.sol +++ b/test/extensions/ERC2981.t.sol @@ -21,37 +21,53 @@ contract ERC2981Test is Test { address private zeroAddress = address(0); function setUp() public { - ERC2981Extended = IERC2981Extended(vyperDeployer.deployContract("src/extensions/", "ERC2981")); + ERC2981Extended = IERC2981Extended( + vyperDeployer.deployContract("src/extensions/", "ERC2981") + ); } function testInitialSetup() public { uint256 tokenId = 1; uint256 salePrice = 1_000; - (address receiver, uint256 royaltyAmount) = ERC2981Extended.royaltyInfo(tokenId, salePrice); + (address receiver, uint256 royaltyAmount) = ERC2981Extended.royaltyInfo( + tokenId, + salePrice + ); assertEq(ERC2981Extended.owner(), deployer); assertEq(receiver, zeroAddress); assertEq(royaltyAmount, 0); vm.expectEmit(true, true, false, false); emit IERC2981Extended.OwnershipTransferred(zeroAddress, deployer); - ERC2981ExtendedInitialEvent = IERC2981Extended(vyperDeployer.deployContract("src/extensions/", "ERC2981")); - (address receiverInitialSetup, uint256 royaltyAmountInitialSetup) = - ERC2981ExtendedInitialEvent.royaltyInfo(tokenId, salePrice); + ERC2981ExtendedInitialEvent = IERC2981Extended( + vyperDeployer.deployContract("src/extensions/", "ERC2981") + ); + ( + address receiverInitialSetup, + uint256 royaltyAmountInitialSetup + ) = ERC2981ExtendedInitialEvent.royaltyInfo(tokenId, salePrice); assertEq(ERC2981ExtendedInitialEvent.owner(), deployer); assertEq(receiverInitialSetup, zeroAddress); assertEq(royaltyAmountInitialSetup, 0); } function testSupportsInterfaceSuccess() public { - assertTrue(ERC2981Extended.supportsInterface(type(IERC165).interfaceId)); - assertTrue(ERC2981Extended.supportsInterface(type(IERC2981).interfaceId)); + assertTrue( + ERC2981Extended.supportsInterface(type(IERC165).interfaceId) + ); + assertTrue( + ERC2981Extended.supportsInterface(type(IERC2981).interfaceId) + ); } function testSupportsInterfaceSuccessGasCost() public { uint256 startGas = gasleft(); ERC2981Extended.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && ERC2981Extended.supportsInterface(type(IERC165).interfaceId)); + assertTrue( + gasUsed <= 30_000 && + ERC2981Extended.supportsInterface(type(IERC165).interfaceId) + ); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -62,7 +78,9 @@ contract ERC2981Test is Test { uint256 startGas = gasleft(); ERC2981Extended.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && !ERC2981Extended.supportsInterface(0x0011bbff)); + assertTrue( + gasUsed <= 30_000 && !ERC2981Extended.supportsInterface(0x0011bbff) + ); } function testRoyaltyInfoDefaultRoyalty() public { @@ -75,8 +93,10 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -98,8 +118,10 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver1, receiverAddr1); @@ -108,8 +130,10 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.set_default_royalty(receiver2, royaltyFraction * 2); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -129,8 +153,10 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -139,8 +165,10 @@ contract ERC2981Test is Test { assertEq(royalty, royaltyAmount2); ERC2981Extended.delete_default_royalty(); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiverAddr3, zeroAddress); @@ -162,9 +190,15 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId1, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertTrue(royaltyAmount1 != royaltyAmount2); assertEq(receiver2, receiverAddr1); @@ -186,9 +220,15 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId1, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertTrue(royaltyAmount1 != royaltyAmount2); assertEq(receiver2, receiverAddr1); @@ -196,9 +236,15 @@ contract ERC2981Test is Test { assertEq(receiver1, receiverAddr2); assertEq(royalty1, royaltyAmount2); - ERC2981Extended.set_token_royalty(tokenId2, receiver2, royaltyFraction * 2); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId2, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -220,9 +266,15 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(owner); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId1, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertTrue(royaltyAmount1 != royaltyAmount2); assertEq(receiver2, receiverAddr1); @@ -231,7 +283,8 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.reset_token_royalty(tokenId1); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); assertEq(receiverAddr3, receiverAddr2); assertEq(royaltyAmount3, royaltyAmount2); assertEq(receiver1, receiverAddr2); @@ -357,8 +410,10 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -377,7 +432,10 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 + receiver1 != zeroAddress && + receiver2 != zeroAddress && + receiver1 != receiver2 && + tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -385,8 +443,10 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver1, receiverAddr1); @@ -395,8 +455,10 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.set_default_royalty(receiver2, royaltyFraction * 2); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -419,8 +481,10 @@ contract ERC2981Test is Test { uint256 royalty = (salePrice * royaltyFraction) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver, royaltyFraction); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr1, receiverAddr2); assertEq(royaltyAmount1, royaltyAmount2); assertEq(receiver, receiverAddr1); @@ -429,8 +493,10 @@ contract ERC2981Test is Test { assertEq(royalty, royaltyAmount2); ERC2981Extended.delete_default_royalty(); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiverAddr3, zeroAddress); @@ -449,7 +515,10 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 + receiver1 != zeroAddress && + receiver2 != zeroAddress && + receiver1 != receiver2 && + tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -457,9 +526,15 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId1, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertEq(receiver2, receiverAddr1); assertEq(royalty2, royaltyAmount1); @@ -477,7 +552,10 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 + receiver1 != zeroAddress && + receiver2 != zeroAddress && + receiver1 != receiver2 && + tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -485,18 +563,30 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId1, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertEq(receiver2, receiverAddr1); assertEq(royalty2, royaltyAmount1); assertEq(receiver1, receiverAddr2); assertEq(royalty1, royaltyAmount2); - ERC2981Extended.set_token_royalty(tokenId2, receiver2, royaltyFraction * 2); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId2, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr4, uint256 royaltyAmount4) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertEq(receiverAddr3, receiverAddr4); assertEq(royaltyAmount3, royaltyAmount4); assertEq(receiver2, receiverAddr3); @@ -515,7 +605,10 @@ contract ERC2981Test is Test { uint256 salePrice ) public { vm.assume( - receiver1 != zeroAddress && receiver2 != zeroAddress && receiver1 != receiver2 && tokenId1 != tokenId2 + receiver1 != zeroAddress && + receiver2 != zeroAddress && + receiver1 != receiver2 && + tokenId1 != tokenId2 ); royaltyFraction = uint96(bound(royaltyFraction, 0, 5_000)); salePrice = bound(salePrice, 0, type(uint240).max); @@ -523,9 +616,15 @@ contract ERC2981Test is Test { uint256 royalty2 = (salePrice * royaltyFraction * 2) / 10_000; vm.startPrank(deployer); ERC2981Extended.set_default_royalty(receiver1, royaltyFraction); - ERC2981Extended.set_token_royalty(tokenId1, receiver2, royaltyFraction * 2); - (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); - (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended.royaltyInfo(tokenId2, salePrice); + ERC2981Extended.set_token_royalty( + tokenId1, + receiver2, + royaltyFraction * 2 + ); + (address receiverAddr1, uint256 royaltyAmount1) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); + (address receiverAddr2, uint256 royaltyAmount2) = ERC2981Extended + .royaltyInfo(tokenId2, salePrice); assertTrue(receiverAddr1 != receiverAddr2); assertEq(receiver2, receiverAddr1); assertEq(royalty2, royaltyAmount1); @@ -533,7 +632,8 @@ contract ERC2981Test is Test { assertEq(royalty1, royaltyAmount2); ERC2981Extended.reset_token_royalty(tokenId1); - (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended.royaltyInfo(tokenId1, salePrice); + (address receiverAddr3, uint256 royaltyAmount3) = ERC2981Extended + .royaltyInfo(tokenId1, salePrice); assertEq(receiverAddr3, receiverAddr2); assertEq(royaltyAmount3, royaltyAmount2); assertEq(receiver1, receiverAddr2); @@ -543,8 +643,12 @@ contract ERC2981Test is Test { vm.stopPrank(); } - function testFuzzSetDefaultRoyaltyTooHighFeeNumerator(uint96 feeNumerator) public { - feeNumerator = uint96(bound(uint256(feeNumerator), 10_001, type(uint96).max)); + function testFuzzSetDefaultRoyaltyTooHighFeeNumerator( + uint96 feeNumerator + ) public { + feeNumerator = uint96( + bound(uint256(feeNumerator), 10_001, type(uint96).max) + ); address owner = deployer; vm.startPrank(owner); vm.expectRevert("ERC2981: royalty fee will exceed sale_price"); @@ -564,12 +668,20 @@ contract ERC2981Test is Test { ERC2981Extended.delete_default_royalty(); } - function testFuzzSetTokenRoyaltyTooHighFeeNumerator(uint96 feeNumerator) public { - feeNumerator = uint96(bound(uint256(feeNumerator), 10_001, type(uint96).max)); + function testFuzzSetTokenRoyaltyTooHighFeeNumerator( + uint96 feeNumerator + ) public { + feeNumerator = uint96( + bound(uint256(feeNumerator), 10_001, type(uint96).max) + ); address owner = deployer; vm.startPrank(owner); vm.expectRevert("ERC2981: royalty fee will exceed sale_price"); - ERC2981Extended.set_token_royalty(1, makeAddr("receiver"), feeNumerator); + ERC2981Extended.set_token_royalty( + 1, + makeAddr("receiver"), + feeNumerator + ); vm.stopPrank(); } @@ -594,7 +706,10 @@ contract ERC2981Test is Test { ERC2981Extended.reset_token_royalty(1); } - function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { + function testFuzzTransferOwnershipSuccess( + address newOwner1, + address newOwner2 + ) public { vm.assume(newOwner1 != zeroAddress && newOwner2 != zeroAddress); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -612,7 +727,10 @@ contract ERC2981Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { + function testFuzzTransferOwnershipNonOwner( + address nonOwner, + address newOwner + ) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -656,7 +774,9 @@ contract ERC2981Invariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - ERC2981Extended = IERC2981Extended(vyperDeployer.deployContract("src/extensions/", "ERC2981")); + ERC2981Extended = IERC2981Extended( + vyperDeployer.deployContract("src/extensions/", "ERC2981") + ); erc2981Handler = new ERC2981Handler(ERC2981Extended, deployer); targetContract(address(erc2981Handler)); targetSender(deployer); @@ -687,7 +807,11 @@ contract ERC2981Handler { erc2981.delete_default_royalty(); } - function set_token_royalty(uint256 tokenId, address receiver, uint96 feeNumerator) public { + function set_token_royalty( + uint256 tokenId, + address receiver, + uint96 feeNumerator + ) public { erc2981.set_token_royalty(tokenId, receiver, feeNumerator); } diff --git a/test/extensions/ERC4626.t.sol b/test/extensions/ERC4626.t.sol index dea6817e..7c526658 100644 --- a/test/extensions/ERC4626.t.sol +++ b/test/extensions/ERC4626.t.sol @@ -24,13 +24,26 @@ contract ERC4626VaultTest is ERC4626Test { uint8 private constant _DECIMALS_OFFSET = 0; uint256 private constant _INITIAL_SUPPLY_UNDERLYING = type(uint8).max; bytes32 private constant _TYPE_HASH = - keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); + keccak256( + bytes( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ) + ); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256(bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")); + keccak256( + bytes( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ) + ); VyperDeployer private vyperDeployer = new VyperDeployer(); ERC20Mock private underlying = - new ERC20Mock(_NAME_UNDERLYING, _SYMBOL_UNDERLYING, makeAddr("initialAccount"), _INITIAL_SUPPLY_UNDERLYING); + new ERC20Mock( + _NAME_UNDERLYING, + _SYMBOL_UNDERLYING, + makeAddr("initialAccount"), + _INITIAL_SUPPLY_UNDERLYING + ); /* solhint-disable var-name-mixedcase */ IERC4626Extended private ERC4626ExtendedDecimalsOffset0; @@ -53,11 +66,24 @@ contract ERC4626VaultTest is ERC4626Test { address private ERC4626ExtendedDecimalsOffset18Addr; function setUp() public override { - bytes memory argsDecimalsOffset0 = - abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET, _NAME_EIP712, _VERSION_EIP712); - ERC4626ExtendedDecimalsOffset0 = - IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset0)); - ERC4626ExtendedDecimalsOffset0Addr = address(ERC4626ExtendedDecimalsOffset0); + bytes memory argsDecimalsOffset0 = abi.encode( + _NAME, + _SYMBOL, + underlying, + _DECIMALS_OFFSET, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC4626ExtendedDecimalsOffset0 = IERC4626Extended( + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffset0 + ) + ); + ERC4626ExtendedDecimalsOffset0Addr = address( + ERC4626ExtendedDecimalsOffset0 + ); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( _TYPE_HASH, @@ -68,23 +94,62 @@ contract ERC4626VaultTest is ERC4626Test { ) ); - bytes memory argsDecimalsOffset6 = - abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET + 6, _NAME_EIP712, _VERSION_EIP712); - ERC4626ExtendedDecimalsOffset6 = - IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset6)); - ERC4626ExtendedDecimalsOffset6Addr = address(ERC4626ExtendedDecimalsOffset6); + bytes memory argsDecimalsOffset6 = abi.encode( + _NAME, + _SYMBOL, + underlying, + _DECIMALS_OFFSET + 6, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC4626ExtendedDecimalsOffset6 = IERC4626Extended( + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffset6 + ) + ); + ERC4626ExtendedDecimalsOffset6Addr = address( + ERC4626ExtendedDecimalsOffset6 + ); - bytes memory argsDecimalsOffset12 = - abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET + 12, _NAME_EIP712, _VERSION_EIP712); - ERC4626ExtendedDecimalsOffset12 = - IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset12)); - ERC4626ExtendedDecimalsOffset12Addr = address(ERC4626ExtendedDecimalsOffset12); + bytes memory argsDecimalsOffset12 = abi.encode( + _NAME, + _SYMBOL, + underlying, + _DECIMALS_OFFSET + 12, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC4626ExtendedDecimalsOffset12 = IERC4626Extended( + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffset12 + ) + ); + ERC4626ExtendedDecimalsOffset12Addr = address( + ERC4626ExtendedDecimalsOffset12 + ); - bytes memory argsDecimalsOffset18 = - abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET + 18, _NAME_EIP712, _VERSION_EIP712); - ERC4626ExtendedDecimalsOffset18 = - IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffset18)); - ERC4626ExtendedDecimalsOffset18Addr = address(ERC4626ExtendedDecimalsOffset18); + bytes memory argsDecimalsOffset18 = abi.encode( + _NAME, + _SYMBOL, + underlying, + _DECIMALS_OFFSET + 18, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC4626ExtendedDecimalsOffset18 = IERC4626Extended( + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffset18 + ) + ); + ERC4626ExtendedDecimalsOffset18Addr = address( + ERC4626ExtendedDecimalsOffset18 + ); /** * @dev ERC-4626 property tests (https://github.com/a16z/erc4626-tests) setup. @@ -120,24 +185,49 @@ contract ERC4626VaultTest is ERC4626Test { /** * @dev Check the case where the asset has not yet been created. */ - bytes memory argsDecimalsOffsetEOA = - abi.encode(_NAME, _SYMBOL, makeAddr("someAccount"), _DECIMALS_OFFSET + 3, _NAME_EIP712, _VERSION_EIP712); + bytes memory argsDecimalsOffsetEOA = abi.encode( + _NAME, + _SYMBOL, + makeAddr("someAccount"), + _DECIMALS_OFFSET + 3, + _NAME_EIP712, + _VERSION_EIP712 + ); // solhint-disable-next-line var-name-mixedcase - IERC4626Extended ERC4626ExtendedDecimalsOffsetEOA = - IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetEOA)); + IERC4626Extended ERC4626ExtendedDecimalsOffsetEOA = IERC4626Extended( + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffsetEOA + ) + ); assertEq(ERC4626ExtendedDecimalsOffsetEOA.name(), _NAME); assertEq(ERC4626ExtendedDecimalsOffsetEOA.symbol(), _SYMBOL); assertEq(ERC4626ExtendedDecimalsOffsetEOA.decimals(), 18 + 3); - assertEq(ERC4626ExtendedDecimalsOffsetEOA.asset(), makeAddr("someAccount")); + assertEq( + ERC4626ExtendedDecimalsOffsetEOA.asset(), + makeAddr("someAccount") + ); /** * @dev Check the case where success is `False`. */ - bytes memory argsDecimalsOffsetNoDecimals = - abi.encode(_NAME, _SYMBOL, deployer, _DECIMALS_OFFSET + 6, _NAME_EIP712, _VERSION_EIP712); + bytes memory argsDecimalsOffsetNoDecimals = abi.encode( + _NAME, + _SYMBOL, + deployer, + _DECIMALS_OFFSET + 6, + _NAME_EIP712, + _VERSION_EIP712 + ); // solhint-disable-next-line var-name-mixedcase - IERC4626Extended ERC4626ExtendedDecimalsOffsetNoDecimals = - IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetNoDecimals)); + IERC4626Extended ERC4626ExtendedDecimalsOffsetNoDecimals = IERC4626Extended( + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffsetNoDecimals + ) + ); assertEq(ERC4626ExtendedDecimalsOffsetNoDecimals.name(), _NAME); assertEq(ERC4626ExtendedDecimalsOffsetNoDecimals.symbol(), _SYMBOL); assertEq(ERC4626ExtendedDecimalsOffsetNoDecimals.decimals(), 18 + 6); @@ -147,26 +237,59 @@ contract ERC4626VaultTest is ERC4626Test { * @dev Check the case where the return value is above the * maximum value of the type `uint8`. */ - address erc20ExcessDecimalsMock = address(new ERC20ExcessDecimalsMock()); - bytes memory argsDecimalsOffsetTooHighDecimals = - abi.encode(_NAME, _SYMBOL, erc20ExcessDecimalsMock, _DECIMALS_OFFSET + 9, _NAME_EIP712, _VERSION_EIP712); + address erc20ExcessDecimalsMock = address( + new ERC20ExcessDecimalsMock() + ); + bytes memory argsDecimalsOffsetTooHighDecimals = abi.encode( + _NAME, + _SYMBOL, + erc20ExcessDecimalsMock, + _DECIMALS_OFFSET + 9, + _NAME_EIP712, + _VERSION_EIP712 + ); // solhint-disable-next-line var-name-mixedcase IERC4626Extended ERC4626ExtendedDecimalsOffsetTooHighDecimals = IERC4626Extended( - vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetTooHighDecimals) - ); + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffsetTooHighDecimals + ) + ); assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.name(), _NAME); - assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.symbol(), _SYMBOL); - assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.decimals(), 18 + 9); - assertEq(ERC4626ExtendedDecimalsOffsetTooHighDecimals.asset(), erc20ExcessDecimalsMock); + assertEq( + ERC4626ExtendedDecimalsOffsetTooHighDecimals.symbol(), + _SYMBOL + ); + assertEq( + ERC4626ExtendedDecimalsOffsetTooHighDecimals.decimals(), + 18 + 9 + ); + assertEq( + ERC4626ExtendedDecimalsOffsetTooHighDecimals.asset(), + erc20ExcessDecimalsMock + ); /** * @dev Check the case where calculated `decimals` value overflows * the `uint8` type. */ - bytes memory argsDecimalsOffsetOverflow = - abi.encode(_NAME, _SYMBOL, underlying, type(uint8).max, _NAME_EIP712, _VERSION_EIP712); + bytes memory argsDecimalsOffsetOverflow = abi.encode( + _NAME, + _SYMBOL, + underlying, + type(uint8).max, + _NAME_EIP712, + _VERSION_EIP712 + ); vm.expectRevert(); - IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", argsDecimalsOffsetOverflow)); + IERC4626Extended( + vyperDeployer.deployContract( + "src/extensions/", + "ERC4626", + argsDecimalsOffsetOverflow + ) + ); } function testEmptyVaultDeposit() public { @@ -176,56 +299,153 @@ contract ERC4626VaultTest is ERC4626Test { uint256 shares = 1; vm.startPrank(holder); underlying.mint(holder, type(uint16).max); - underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint256).max); - underlying.approve(ERC4626ExtendedDecimalsOffset6Addr, type(uint256).max); - underlying.approve(ERC4626ExtendedDecimalsOffset12Addr, type(uint256).max); - underlying.approve(ERC4626ExtendedDecimalsOffset18Addr, type(uint256).max); + underlying.approve( + ERC4626ExtendedDecimalsOffset0Addr, + type(uint256).max + ); + underlying.approve( + ERC4626ExtendedDecimalsOffset6Addr, + type(uint256).max + ); + underlying.approve( + ERC4626ExtendedDecimalsOffset12Addr, + type(uint256).max + ); + underlying.approve( + ERC4626ExtendedDecimalsOffset18Addr, + type(uint256).max + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.maxDeposit(holder), type(uint256).max); + assertEq( + ERC4626ExtendedDecimalsOffset0.maxDeposit(holder), + type(uint256).max + ); assertEq(ERC4626ExtendedDecimalsOffset0.previewDeposit(assets), shares); assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset6.maxDeposit(holder), type(uint256).max); - assertEq(ERC4626ExtendedDecimalsOffset6.previewDeposit(assets), shares * 10 ** 6); + assertEq( + ERC4626ExtendedDecimalsOffset6.maxDeposit(holder), + type(uint256).max + ); + assertEq( + ERC4626ExtendedDecimalsOffset6.previewDeposit(assets), + shares * 10 ** 6 + ); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset12.maxDeposit(holder), type(uint256).max); - assertEq(ERC4626ExtendedDecimalsOffset12.previewDeposit(assets), shares * 10 ** 12); + assertEq( + ERC4626ExtendedDecimalsOffset12.maxDeposit(holder), + type(uint256).max + ); + assertEq( + ERC4626ExtendedDecimalsOffset12.previewDeposit(assets), + shares * 10 ** 12 + ); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset18.maxDeposit(holder), type(uint256).max); - assertEq(ERC4626ExtendedDecimalsOffset18.previewDeposit(assets), shares * 10 ** 18); + assertEq( + ERC4626ExtendedDecimalsOffset18.maxDeposit(holder), + type(uint256).max + ); + assertEq( + ERC4626ExtendedDecimalsOffset18.previewDeposit(assets), + shares * 10 ** 18 + ); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset0Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset0Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares); ERC4626ExtendedDecimalsOffset0.deposit(assets, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset6Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset6Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 6); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 6); ERC4626ExtendedDecimalsOffset6.deposit(assets, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset12Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset12Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 12); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 12); ERC4626ExtendedDecimalsOffset12.deposit(assets, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset18Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset18Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 18); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 18); ERC4626ExtendedDecimalsOffset18.deposit(assets, receiver); @@ -237,18 +457,36 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(holder), 0); - assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), shares * 10 ** 6); - assertEq(ERC4626ExtendedDecimalsOffset6.totalSupply(), shares * 10 ** 6); + assertEq( + ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), + shares * 10 ** 6 + ); + assertEq( + ERC4626ExtendedDecimalsOffset6.totalSupply(), + shares * 10 ** 6 + ); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(holder), 0); - assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), shares * 10 ** 12); - assertEq(ERC4626ExtendedDecimalsOffset12.totalSupply(), shares * 10 ** 12); + assertEq( + ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), + shares * 10 ** 12 + ); + assertEq( + ERC4626ExtendedDecimalsOffset12.totalSupply(), + shares * 10 ** 12 + ); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(holder), 0); - assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), shares * 10 ** 18); - assertEq(ERC4626ExtendedDecimalsOffset18.totalSupply(), shares * 10 ** 18); + assertEq( + ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), + shares * 10 ** 18 + ); + assertEq( + ERC4626ExtendedDecimalsOffset18.totalSupply(), + shares * 10 ** 18 + ); vm.stopPrank(); } @@ -259,56 +497,153 @@ contract ERC4626VaultTest is ERC4626Test { uint256 shares = 1; vm.startPrank(holder); underlying.mint(holder, type(uint16).max); - underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint256).max); - underlying.approve(ERC4626ExtendedDecimalsOffset6Addr, type(uint256).max); - underlying.approve(ERC4626ExtendedDecimalsOffset12Addr, type(uint256).max); - underlying.approve(ERC4626ExtendedDecimalsOffset18Addr, type(uint256).max); + underlying.approve( + ERC4626ExtendedDecimalsOffset0Addr, + type(uint256).max + ); + underlying.approve( + ERC4626ExtendedDecimalsOffset6Addr, + type(uint256).max + ); + underlying.approve( + ERC4626ExtendedDecimalsOffset12Addr, + type(uint256).max + ); + underlying.approve( + ERC4626ExtendedDecimalsOffset18Addr, + type(uint256).max + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.maxMint(receiver), type(uint256).max); + assertEq( + ERC4626ExtendedDecimalsOffset0.maxMint(receiver), + type(uint256).max + ); assertEq(ERC4626ExtendedDecimalsOffset0.previewMint(shares), assets); assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset6.maxMint(receiver), type(uint256).max); - assertEq(ERC4626ExtendedDecimalsOffset6.previewMint(shares * 10 ** 6), assets); + assertEq( + ERC4626ExtendedDecimalsOffset6.maxMint(receiver), + type(uint256).max + ); + assertEq( + ERC4626ExtendedDecimalsOffset6.previewMint(shares * 10 ** 6), + assets + ); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset12.maxMint(receiver), type(uint256).max); - assertEq(ERC4626ExtendedDecimalsOffset12.previewMint(shares * 10 ** 12), assets); + assertEq( + ERC4626ExtendedDecimalsOffset12.maxMint(receiver), + type(uint256).max + ); + assertEq( + ERC4626ExtendedDecimalsOffset12.previewMint(shares * 10 ** 12), + assets + ); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), 0); - assertEq(ERC4626ExtendedDecimalsOffset18.maxMint(receiver), type(uint256).max); - assertEq(ERC4626ExtendedDecimalsOffset18.previewMint(shares * 10 ** 18), assets); + assertEq( + ERC4626ExtendedDecimalsOffset18.maxMint(receiver), + type(uint256).max + ); + assertEq( + ERC4626ExtendedDecimalsOffset18.previewMint(shares * 10 ** 18), + assets + ); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset0Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset0Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares); ERC4626ExtendedDecimalsOffset0.mint(shares, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset6Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset6Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 6); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 6); ERC4626ExtendedDecimalsOffset6.mint(shares * 10 ** 6, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset12Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset12Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 12); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 12); ERC4626ExtendedDecimalsOffset12.mint(shares * 10 ** 12, receiver); vm.expectEmit(true, true, false, true, underlyingAddr); - emit IERC20.Transfer(holder, ERC4626ExtendedDecimalsOffset18Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); + emit IERC20.Transfer( + holder, + ERC4626ExtendedDecimalsOffset18Addr, + assets + ); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC20.Transfer(zeroAddress, receiver, shares * 10 ** 18); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC4626.Deposit(holder, receiver, assets, shares * 10 ** 18); ERC4626ExtendedDecimalsOffset18.mint(shares * 10 ** 18, receiver); @@ -320,18 +655,36 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset6.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(holder), 0); - assertEq(ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), shares * 10 ** 6); - assertEq(ERC4626ExtendedDecimalsOffset6.totalSupply(), shares * 10 ** 6); + assertEq( + ERC4626ExtendedDecimalsOffset6.balanceOf(receiver), + shares * 10 ** 6 + ); + assertEq( + ERC4626ExtendedDecimalsOffset6.totalSupply(), + shares * 10 ** 6 + ); assertEq(ERC4626ExtendedDecimalsOffset12.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(holder), 0); - assertEq(ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), shares * 10 ** 12); - assertEq(ERC4626ExtendedDecimalsOffset12.totalSupply(), shares * 10 ** 12); + assertEq( + ERC4626ExtendedDecimalsOffset12.balanceOf(receiver), + shares * 10 ** 12 + ); + assertEq( + ERC4626ExtendedDecimalsOffset12.totalSupply(), + shares * 10 ** 12 + ); assertEq(ERC4626ExtendedDecimalsOffset18.totalAssets(), assets); assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(holder), 0); - assertEq(ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), shares * 10 ** 18); - assertEq(ERC4626ExtendedDecimalsOffset18.totalSupply(), shares * 10 ** 18); + assertEq( + ERC4626ExtendedDecimalsOffset18.balanceOf(receiver), + shares * 10 ** 18 + ); + assertEq( + ERC4626ExtendedDecimalsOffset18.totalSupply(), + shares * 10 ** 18 + ); vm.stopPrank(); } @@ -355,35 +708,83 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset18.maxWithdraw(holder), 0); assertEq(ERC4626ExtendedDecimalsOffset18.previewWithdraw(0), 0); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset0.withdraw(0, receiver, holder); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset6Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset6Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset6.withdraw(0, receiver, holder); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset12Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset12Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset12.withdraw(0, receiver, holder); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset18Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset18Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset18.withdraw(0, receiver, holder); @@ -430,35 +831,83 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset18.maxRedeem(holder), 0); assertEq(ERC4626ExtendedDecimalsOffset18.previewRedeem(0), 0); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset0.redeem(0, receiver, holder); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset6Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset6Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset6Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset6Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset6.redeem(0, receiver, holder); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset12Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset12Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset12Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset12Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset12.redeem(0, receiver, holder); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset18Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC20.Transfer(holder, zeroAddress, 0); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset18Addr, receiver, 0); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset18Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset18Addr + ); emit IERC4626.Withdraw(holder, receiver, holder, 0, 0); ERC4626ExtendedDecimalsOffset18.redeem(0, receiver, holder); @@ -497,39 +946,89 @@ contract ERC4626VaultTest is ERC4626Test { vm.startPrank(alice); underlying.mint(alice, assets); underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, assets); - assertEq(underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), assets); + assertEq( + underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), + assets + ); uint256 alicePreDepositBalance = underlying.balanceOf(alice); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(alice, ERC4626ExtendedDecimalsOffset0Addr, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(zeroAddress, alice, assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Deposit(alice, alice, assets, assets); - uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0.deposit(assets, alice); + uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0.deposit( + assets, + alice + ); assertEq(assets, aliceShareAmount); - assertEq(ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceShareAmount), assets); - assertEq(ERC4626ExtendedDecimalsOffset0.previewDeposit(assets), aliceShareAmount); - assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), aliceShareAmount); + assertEq( + ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceShareAmount), + assets + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.previewDeposit(assets), + aliceShareAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.totalSupply(), + aliceShareAmount + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), assets); - assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), assets + ERC4626ExtendedDecimalsOffset0.balanceOf(alice), + aliceShareAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + assets ); assertEq(underlying.balanceOf(alice), alicePreDepositBalance - assets); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(alice, zeroAddress, assets); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, alice, assets); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Withdraw(alice, alice, alice, assets, assets); ERC4626ExtendedDecimalsOffset0.withdraw(assets, alice, alice); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 0 + ); assertEq(underlying.balanceOf(alice), alicePreDepositBalance); vm.stopPrank(); } @@ -544,39 +1043,89 @@ contract ERC4626VaultTest is ERC4626Test { vm.startPrank(alice); underlying.mint(alice, shares); underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, shares); - assertEq(underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), shares); + assertEq( + underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), + shares + ); uint256 alicePreDepositBalance = underlying.balanceOf(alice); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(alice, ERC4626ExtendedDecimalsOffset0Addr, shares); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(zeroAddress, alice, shares); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Deposit(alice, alice, shares, shares); - uint256 aliceAssetAmount = ERC4626ExtendedDecimalsOffset0.mint(shares, alice); + uint256 aliceAssetAmount = ERC4626ExtendedDecimalsOffset0.mint( + shares, + alice + ); assertEq(aliceAssetAmount, shares); - assertEq(ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceAssetAmount), shares); - assertEq(ERC4626ExtendedDecimalsOffset0.previewDeposit(shares), aliceAssetAmount); - assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), aliceAssetAmount); + assertEq( + ERC4626ExtendedDecimalsOffset0.previewWithdraw(aliceAssetAmount), + shares + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.previewDeposit(shares), + aliceAssetAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.totalSupply(), + aliceAssetAmount + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), shares); - assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceAssetAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), shares + ERC4626ExtendedDecimalsOffset0.balanceOf(alice), + aliceAssetAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + shares ); assertEq(underlying.balanceOf(alice), alicePreDepositBalance - shares); - vm.expectEmit(true, true, false, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + false, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC20.Transfer(alice, zeroAddress, shares); vm.expectEmit(true, true, false, true, underlyingAddr); emit IERC20.Transfer(ERC4626ExtendedDecimalsOffset0Addr, alice, shares); - vm.expectEmit(true, true, true, true, ERC4626ExtendedDecimalsOffset0Addr); + vm.expectEmit( + true, + true, + true, + true, + ERC4626ExtendedDecimalsOffset0Addr + ); emit IERC4626.Withdraw(alice, alice, alice, shares, shares); ERC4626ExtendedDecimalsOffset0.redeem(shares, alice, alice); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 0 + ); assertEq(underlying.balanceOf(alice), alicePreDepositBalance); vm.stopPrank(); } @@ -593,47 +1142,82 @@ contract ERC4626VaultTest is ERC4626Test { uint256 mutationUnderlyingAmount = 3_000; vm.startPrank(alice); underlying.mint(alice, initialAmountAlice); - underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, initialAmountAlice); - assertEq(underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), initialAmountAlice); + underlying.approve( + ERC4626ExtendedDecimalsOffset0Addr, + initialAmountAlice + ); + assertEq( + underlying.allowance(alice, ERC4626ExtendedDecimalsOffset0Addr), + initialAmountAlice + ); vm.stopPrank(); vm.startPrank(bob); underlying.mint(bob, initialAmountBob); - underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, initialAmountBob); - assertEq(underlying.allowance(bob, ERC4626ExtendedDecimalsOffset0Addr), initialAmountBob); + underlying.approve( + ERC4626ExtendedDecimalsOffset0Addr, + initialAmountBob + ); + assertEq( + underlying.allowance(bob, ERC4626ExtendedDecimalsOffset0Addr), + initialAmountBob + ); vm.stopPrank(); /** * @dev 1. Alice mints 2,000 shares (costs 2,000 tokens). */ vm.startPrank(alice); - uint256 aliceUnderlyingAmount = ERC4626ExtendedDecimalsOffset0.mint(2_000, alice); - uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0.previewDeposit(aliceUnderlyingAmount); + uint256 aliceUnderlyingAmount = ERC4626ExtendedDecimalsOffset0.mint( + 2_000, + alice + ); + uint256 aliceShareAmount = ERC4626ExtendedDecimalsOffset0 + .previewDeposit(aliceUnderlyingAmount); assertEq(aliceShareAmount, 2_000); - assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), + ERC4626ExtendedDecimalsOffset0.balanceOf(alice), + aliceShareAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), aliceUnderlyingAmount ); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToShares(aliceUnderlyingAmount), + ERC4626ExtendedDecimalsOffset0.convertToShares( + aliceUnderlyingAmount + ), ERC4626ExtendedDecimalsOffset0.balanceOf(alice) ); assertEq(aliceUnderlyingAmount, 2_000); - assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), aliceShareAmount); - assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), aliceUnderlyingAmount); + assertEq( + ERC4626ExtendedDecimalsOffset0.totalSupply(), + aliceShareAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.totalAssets(), + aliceUnderlyingAmount + ); vm.stopPrank(); /** * @dev 2. Bob deposits 4,000 tokens (mints 4,000 shares). */ vm.startPrank(bob); - uint256 bobShareAmount = ERC4626ExtendedDecimalsOffset0.deposit(4_000, bob); - uint256 bobUnderlyingAmount = ERC4626ExtendedDecimalsOffset0.previewWithdraw(bobShareAmount); + uint256 bobShareAmount = ERC4626ExtendedDecimalsOffset0.deposit( + 4_000, + bob + ); + uint256 bobUnderlyingAmount = ERC4626ExtendedDecimalsOffset0 + .previewWithdraw(bobShareAmount); assertEq(bobUnderlyingAmount, 4_000); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), bobShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), bobUnderlyingAmount ); assertEq( @@ -643,7 +1227,10 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(bobShareAmount, bobUnderlyingAmount); uint256 preMutationShareBal = aliceShareAmount + bobShareAmount; uint256 preMutationBal = aliceUnderlyingAmount + bobUnderlyingAmount; - assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), preMutationShareBal); + assertEq( + ERC4626ExtendedDecimalsOffset0.totalSupply(), + preMutationShareBal + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), preMutationBal); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 6_000); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 6_000); @@ -652,17 +1239,33 @@ contract ERC4626VaultTest is ERC4626Test { /** * @dev 3. Vault mutates by +3,000 tokens (simulated yield returned from strategy). */ - underlying.mint(ERC4626ExtendedDecimalsOffset0Addr, mutationUnderlyingAmount); - assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), preMutationShareBal); - assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), preMutationBal + mutationUnderlyingAmount); - assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), aliceShareAmount); + underlying.mint( + ERC4626ExtendedDecimalsOffset0Addr, + mutationUnderlyingAmount + ); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), + ERC4626ExtendedDecimalsOffset0.totalSupply(), + preMutationShareBal + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.totalAssets(), + preMutationBal + mutationUnderlyingAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice), + aliceShareAmount + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), aliceUnderlyingAmount + (mutationUnderlyingAmount / 3) * 1 - 1 ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), bobShareAmount); assertEq( - ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), bobUnderlyingAmount + (mutationUnderlyingAmount / 3) * 2 - 1 ); @@ -673,9 +1276,19 @@ contract ERC4626VaultTest is ERC4626Test { ERC4626ExtendedDecimalsOffset0.deposit(2_000, alice); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 7_333); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 3_333); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 4_999); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 4_999 + ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 4_000); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 6_000); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), + 6_000 + ); vm.stopPrank(); /** @@ -687,9 +1300,19 @@ contract ERC4626VaultTest is ERC4626Test { ERC4626ExtendedDecimalsOffset0.mint(2_000, bob); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 9_333); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 3_333); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 4_999); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 4_999 + ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 6_000); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 9_000); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), + 9_000 + ); assertEq(underlying.balanceOf(alice), 0); assertEq(underlying.balanceOf(bob), 1); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 14_000); @@ -698,10 +1321,23 @@ contract ERC4626VaultTest is ERC4626Test { /** * @dev 6. Vault mutates by +3,000 tokens. */ - underlying.mint(ERC4626ExtendedDecimalsOffset0Addr, mutationUnderlyingAmount); + underlying.mint( + ERC4626ExtendedDecimalsOffset0Addr, + mutationUnderlyingAmount + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 17_000); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 6_070); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 10_928); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 6_070 + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), + 10_928 + ); /** * @dev 7. Alice redeems 1,333 shares (2,427 assets). @@ -712,9 +1348,19 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 8_000); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 14_573); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 2_000); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 3_643); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 3_643 + ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 6_000); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 10_929); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), + 10_929 + ); vm.stopPrank(); /** @@ -726,9 +1372,19 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 6_392); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 11_644); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 2_000); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 3_643); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 3_643 + ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 4_392); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 8_000); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), + 8_000 + ); vm.stopPrank(); /** @@ -741,9 +1397,19 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 4_392); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 8_001); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 0 + ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 4_392); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 8_000); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), + 8_000 + ); vm.stopPrank(); /** @@ -755,17 +1421,33 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 1); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(alice), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(alice)), 0); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(alice) + ), + 0 + ); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(bob), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(bob)), 0); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(bob) + ), + 0 + ); assertEq(underlying.balanceOf(ERC4626ExtendedDecimalsOffset0Addr), 1); vm.stopPrank(); } function testDepositInsufficientAllowance() public { underlying.mint(self, type(uint8).max); - underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint8).max - 1); - assertEq(underlying.allowance(self, ERC4626ExtendedDecimalsOffset0Addr), type(uint8).max - 1); + underlying.approve( + ERC4626ExtendedDecimalsOffset0Addr, + type(uint8).max - 1 + ); + assertEq( + underlying.allowance(self, ERC4626ExtendedDecimalsOffset0Addr), + type(uint8).max - 1 + ); vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientAllowance.selector, @@ -782,7 +1464,11 @@ contract ERC4626VaultTest is ERC4626Test { underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint8).max); ERC4626ExtendedDecimalsOffset0.deposit(type(uint8).max, self); vm.expectRevert(bytes("ERC4626: withdraw more than maximum")); - ERC4626ExtendedDecimalsOffset0.withdraw(uint256(type(uint8).max) + 1, self, self); + ERC4626ExtendedDecimalsOffset0.withdraw( + uint256(type(uint8).max) + 1, + self, + self + ); } function testWithdrawInsufficientAllowance() public { @@ -799,7 +1485,11 @@ contract ERC4626VaultTest is ERC4626Test { underlying.approve(ERC4626ExtendedDecimalsOffset0Addr, type(uint8).max); ERC4626ExtendedDecimalsOffset0.deposit(type(uint8).max, self); vm.expectRevert(bytes("ERC4626: redeem more than maximum")); - ERC4626ExtendedDecimalsOffset0.redeem(uint256(type(uint8).max) + 1, self, self); + ERC4626ExtendedDecimalsOffset0.redeem( + uint256(type(uint8).max) + 1, + self, + self + ); } function testWithdrawWithNoAssets() public { @@ -815,7 +1505,10 @@ contract ERC4626VaultTest is ERC4626Test { function testDepositWithNoApproval() public { vm.expectRevert( abi.encodeWithSelector( - IERC20Errors.ERC20InsufficientAllowance.selector, ERC4626ExtendedDecimalsOffset0Addr, 0, type(uint8).max + IERC20Errors.ERC20InsufficientAllowance.selector, + ERC4626ExtendedDecimalsOffset0Addr, + 0, + type(uint8).max ) ); ERC4626ExtendedDecimalsOffset0.deposit(type(uint8).max, self); @@ -824,7 +1517,10 @@ contract ERC4626VaultTest is ERC4626Test { function testMintWithNoApproval() public { vm.expectRevert( abi.encodeWithSelector( - IERC20Errors.ERC20InsufficientAllowance.selector, ERC4626ExtendedDecimalsOffset0Addr, 0, type(uint8).max + IERC20Errors.ERC20InsufficientAllowance.selector, + ERC4626ExtendedDecimalsOffset0Addr, + 0, + type(uint8).max ) ); ERC4626ExtendedDecimalsOffset0.mint(type(uint8).max, self); @@ -833,7 +1529,12 @@ contract ERC4626VaultTest is ERC4626Test { function testDepositZero() public { ERC4626ExtendedDecimalsOffset0.deposit(0, self); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(self), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(self)), 0); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(self) + ), + 0 + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); } @@ -841,7 +1542,12 @@ contract ERC4626VaultTest is ERC4626Test { function testMintZero() public { ERC4626ExtendedDecimalsOffset0.mint(0, self); assertEq(ERC4626ExtendedDecimalsOffset0.balanceOf(self), 0); - assertEq(ERC4626ExtendedDecimalsOffset0.convertToAssets(ERC4626ExtendedDecimalsOffset0.balanceOf(self)), 0); + assertEq( + ERC4626ExtendedDecimalsOffset0.convertToAssets( + ERC4626ExtendedDecimalsOffset0.balanceOf(self) + ), + 0 + ); assertEq(ERC4626ExtendedDecimalsOffset0.totalSupply(), 0); assertEq(ERC4626ExtendedDecimalsOffset0.totalAssets(), 0); } @@ -892,21 +1598,42 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 + .DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectEmit(true, true, false, true); emit IERC20.Approval(owner, spender, amount); - ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); - assertEq(ERC4626ExtendedDecimalsOffset0.allowance(owner, spender), amount); + ERC4626ExtendedDecimalsOffset0.permit( + owner, + spender, + amount, + deadline, + v, + r, + s + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.allowance(owner, spender), + amount + ); assertEq(ERC4626ExtendedDecimalsOffset0.nonces(owner), 1); } @@ -917,22 +1644,48 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 + .DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectEmit(true, true, false, true); emit IERC20.Approval(owner, spender, amount); - ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); + ERC4626ExtendedDecimalsOffset0.permit( + owner, + spender, + amount, + deadline, + v, + r, + s + ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); + ERC4626ExtendedDecimalsOffset0.permit( + owner, + spender, + amount, + deadline, + v, + r, + s + ); } function testPermitOtherSignature() public { @@ -942,19 +1695,37 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 + .DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key + 1, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); + ERC4626ExtendedDecimalsOffset0.permit( + owner, + spender, + amount, + deadline, + v, + r, + s + ); } function testPermitBadChainId() public { @@ -979,12 +1750,29 @@ contract ERC4626VaultTest is ERC4626Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); + ERC4626ExtendedDecimalsOffset0.permit( + owner, + spender, + amount, + deadline, + v, + r, + s + ); } function testPermitBadNonce() public { @@ -994,19 +1782,37 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = 1; // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 + .DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); + ERC4626ExtendedDecimalsOffset0.permit( + owner, + spender, + amount, + deadline, + v, + r, + s + ); } function testPermitExpiredDeadline() public { @@ -1016,23 +1822,44 @@ contract ERC4626VaultTest is ERC4626Test { uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp - 1; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 + .DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectRevert(bytes("ERC20Permit: expired deadline")); - ERC4626ExtendedDecimalsOffset0.permit(owner, spender, amount, deadline, v, r, s); + ERC4626ExtendedDecimalsOffset0.permit( + owner, + spender, + amount, + deadline, + v, + r, + s + ); } function testCachedDomainSeparator() public { - assertEq(ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), _CACHED_DOMAIN_SEPARATOR); + assertEq( + ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), + _CACHED_DOMAIN_SEPARATOR + ); } function testDomainSeparator() public { @@ -1068,58 +1895,113 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), digest); } - function testFuzzPermitSuccess(string calldata owner, string calldata spender, uint16 increment) public { + function testFuzzPermitSuccess( + string calldata owner, + string calldata spender, + uint16 increment + ) public { (address ownerAddr, uint256 key) = makeAddrAndKey(owner); address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 + .DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( key, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + ownerAddr, + spenderAddr, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectEmit(true, true, false, true); emit IERC20.Approval(ownerAddr, spenderAddr, amount); - ERC4626ExtendedDecimalsOffset0.permit(ownerAddr, spenderAddr, amount, deadline, v, r, s); - assertEq(ERC4626ExtendedDecimalsOffset0.allowance(ownerAddr, spenderAddr), amount); + ERC4626ExtendedDecimalsOffset0.permit( + ownerAddr, + spenderAddr, + amount, + deadline, + v, + r, + s + ); + assertEq( + ERC4626ExtendedDecimalsOffset0.allowance(ownerAddr, spenderAddr), + amount + ); assertEq(ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr), 1); } - function testFuzzPermitInvalid(string calldata owner, string calldata spender, uint16 increment) public { - vm.assume(keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong"))); - (address ownerAddr,) = makeAddrAndKey(owner); + function testFuzzPermitInvalid( + string calldata owner, + string calldata spender, + uint16 increment + ) public { + vm.assume( + keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong")) + ); + (address ownerAddr, ) = makeAddrAndKey(owner); (, uint256 keyWrong) = makeAddrAndKey("ownerWrong"); address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr); // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; - bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(); + bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 + .DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( keyWrong, keccak256( abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + ownerAddr, + spenderAddr, + amount, + nonce, + deadline + ) + ) ) ) ); vm.expectRevert(bytes("ERC20Permit: invalid signature")); - ERC4626ExtendedDecimalsOffset0.permit(ownerAddr, spenderAddr, amount, deadline, v, r, s); + ERC4626ExtendedDecimalsOffset0.permit( + ownerAddr, + spenderAddr, + amount, + deadline, + v, + r, + s + ); } function testFuzzDomainSeparator(uint8 increment) public { @@ -1142,7 +2024,11 @@ contract ERC4626VaultTest is ERC4626Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); + vm.assume( + randomHex != hex"0f" && + randomSalt != bytes32(0) && + randomExtensions.length != 0 + ); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -1159,10 +2045,19 @@ contract ERC4626VaultTest is ERC4626Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, ERC4626ExtendedDecimalsOffset0Addr); assertTrue(salt != randomSalt); - assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); + assertTrue( + keccak256(abi.encode(extensions)) != + keccak256(abi.encode(randomExtensions)) + ); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(ERC4626ExtendedDecimalsOffset0.DOMAIN_SEPARATOR(), digest); } @@ -1181,26 +2076,46 @@ contract ERC4626VaultInvariants is Test { VyperDeployer private vyperDeployer = new VyperDeployer(); address private deployer = address(vyperDeployer); ERC20Mock private underlying = - new ERC20Mock(_NAME_UNDERLYING, _SYMBOL_UNDERLYING, deployer, _INITIAL_SUPPLY_UNDERLYING); + new ERC20Mock( + _NAME_UNDERLYING, + _SYMBOL_UNDERLYING, + deployer, + _INITIAL_SUPPLY_UNDERLYING + ); // solhint-disable-next-line var-name-mixedcase IERC4626Extended private ERC4626Extended; ERC4626VaultHandler private erc4626VaultHandler; function setUp() public { - bytes memory args = abi.encode(_NAME, _SYMBOL, underlying, _DECIMALS_OFFSET, _NAME_EIP712, _VERSION_EIP712); - ERC4626Extended = IERC4626Extended(vyperDeployer.deployContract("src/extensions/", "ERC4626", args)); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + underlying, + _DECIMALS_OFFSET, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC4626Extended = IERC4626Extended( + vyperDeployer.deployContract("src/extensions/", "ERC4626", args) + ); erc4626VaultHandler = new ERC4626VaultHandler(ERC4626Extended); targetContract(address(erc4626VaultHandler)); targetSender(deployer); } function invariantTotalSupply() public { - assertEq(ERC4626Extended.totalSupply(), erc4626VaultHandler.totalSupply()); + assertEq( + ERC4626Extended.totalSupply(), + erc4626VaultHandler.totalSupply() + ); } function invariantTotalAssets() public { - assertEq(ERC4626Extended.totalAssets(), erc4626VaultHandler.totalAssets()); + assertEq( + ERC4626Extended.totalAssets(), + erc4626VaultHandler.totalAssets() + ); } } @@ -1226,9 +2141,15 @@ contract ERC4626VaultHandler { vault.transferFrom(owner, to, amount); } - function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) - public - { + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { vault.permit(owner, spender, value, deadline, v, r, s); } diff --git a/test/extensions/interfaces/IERC2981Extended.sol b/test/extensions/interfaces/IERC2981Extended.sol index c360ab97..043302c0 100644 --- a/test/extensions/interfaces/IERC2981Extended.sol +++ b/test/extensions/interfaces/IERC2981Extended.sol @@ -4,13 +4,23 @@ pragma solidity ^0.8.23; import {IERC2981} from "openzeppelin/interfaces/IERC2981.sol"; interface IERC2981Extended is IERC2981 { - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); - function set_default_royalty(address receiver, uint96 feeNumerator) external; + function set_default_royalty( + address receiver, + uint96 feeNumerator + ) external; function delete_default_royalty() external; - function set_token_royalty(uint256 tokenId, address receiver, uint96 feeNumerator) external; + function set_token_royalty( + uint256 tokenId, + address receiver, + uint96 feeNumerator + ) external; function reset_token_royalty(uint256 tokenId) external; diff --git a/test/extensions/interfaces/IERC4626Extended.sol b/test/extensions/interfaces/IERC4626Extended.sol index ca1a68ea..1c225583 100644 --- a/test/extensions/interfaces/IERC4626Extended.sol +++ b/test/extensions/interfaces/IERC4626Extended.sol @@ -7,4 +7,9 @@ import {IERC4626} from "openzeppelin/interfaces/IERC4626.sol"; import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; // solhint-disable-next-line no-empty-blocks -interface IERC4626Extended is IERC20Metadata, IERC20Permit, IERC4626, IERC5267 {} +interface IERC4626Extended is + IERC20Metadata, + IERC20Permit, + IERC4626, + IERC5267 +{} diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index d3292d39..85a16bd2 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -57,42 +57,117 @@ contract TimelockControllerTest is Test { executors[1] = EXECUTOR_TWO; bytes memory args = abi.encode(MIN_DELAY, proposers, executors, ADMIN); - timelockController = - TimelockController(payable(vyperDeployer.deployContract("src/governance/", "TimelockController", args))); + timelockController = TimelockController( + payable( + vyperDeployer.deployContract( + "src/governance/", + "TimelockController", + args + ) + ) + ); counter = new Counter(address(timelockController)); - calls.push(Call({target: address(counter), value: 0, data: abi.encodeWithSelector(Counter.increment.selector)})); calls.push( - Call({target: address(counter), value: 0, data: abi.encodeWithSelector(Counter.setNumber.selector, 10)}) + Call({ + target: address(counter), + value: 0, + data: abi.encodeWithSelector(Counter.increment.selector) + }) + ); + calls.push( + Call({ + target: address(counter), + value: 0, + data: abi.encodeWithSelector(Counter.setNumber.selector, 10) + }) ); } - function checkRoleNotSetForAddresses(TimelockController timelock, bytes32 role, address[2] storage addresses) - internal - { + function checkRoleNotSetForAddresses( + TimelockController timelock, + bytes32 role, + address[2] storage addresses + ) internal { for (uint256 i = 0; i < addresses.length; ++i) { assertFalse(timelock.hasRole(role, addresses[i])); } } function testInitialSetup() public { - assertEq(timelockController.hasRole(timelockController.DEFAULT_ADMIN_ROLE(), address(this)), true); + assertEq( + timelockController.hasRole( + timelockController.DEFAULT_ADMIN_ROLE(), + address(this) + ), + true + ); - checkRoleNotSetForAddresses(timelockController, timelockController.DEFAULT_ADMIN_ROLE(), PROPOSERS); - checkRoleNotSetForAddresses(timelockController, timelockController.DEFAULT_ADMIN_ROLE(), EXECUTORS); + checkRoleNotSetForAddresses( + timelockController, + timelockController.DEFAULT_ADMIN_ROLE(), + PROPOSERS + ); + checkRoleNotSetForAddresses( + timelockController, + timelockController.DEFAULT_ADMIN_ROLE(), + EXECUTORS + ); - assertEq(timelockController.hasRole(timelockController.PROPOSER_ROLE(), PROPOSER_ONE), true); - assertEq(timelockController.hasRole(timelockController.PROPOSER_ROLE(), PROPOSER_TWO), true); + assertEq( + timelockController.hasRole( + timelockController.PROPOSER_ROLE(), + PROPOSER_ONE + ), + true + ); + assertEq( + timelockController.hasRole( + timelockController.PROPOSER_ROLE(), + PROPOSER_TWO + ), + true + ); - assertFalse(timelockController.hasRole(timelockController.PROPOSER_ROLE(), ADMIN)); + assertFalse( + timelockController.hasRole( + timelockController.PROPOSER_ROLE(), + ADMIN + ) + ); - checkRoleNotSetForAddresses(timelockController, timelockController.PROPOSER_ROLE(), EXECUTORS); + checkRoleNotSetForAddresses( + timelockController, + timelockController.PROPOSER_ROLE(), + EXECUTORS + ); - assertEq(timelockController.hasRole(timelockController.EXECUTOR_ROLE(), EXECUTOR_ONE), true); - assertEq(timelockController.hasRole(timelockController.EXECUTOR_ROLE(), EXECUTOR_TWO), true); - assertFalse(timelockController.hasRole(timelockController.EXECUTOR_ROLE(), ADMIN)); - checkRoleNotSetForAddresses(timelockController, timelockController.EXECUTOR_ROLE(), PROPOSERS); + assertEq( + timelockController.hasRole( + timelockController.EXECUTOR_ROLE(), + EXECUTOR_ONE + ), + true + ); + assertEq( + timelockController.hasRole( + timelockController.EXECUTOR_ROLE(), + EXECUTOR_TWO + ), + true + ); + assertFalse( + timelockController.hasRole( + timelockController.EXECUTOR_ROLE(), + ADMIN + ) + ); + checkRoleNotSetForAddresses( + timelockController, + timelockController.EXECUTOR_ROLE(), + PROPOSERS + ); assertEq(timelockController.getMinDelay(), MIN_DELAY); // TODO: Add event emit checks. @@ -108,14 +183,26 @@ contract TimelockControllerTest is Test { values[1] = 1; bytes[] memory payloads = new bytes[](2); - payloads[0] = abi.encodeWithSelector(this.testHashesBatchedOperationsCorrectly.selector); - payloads[1] = abi.encodeWithSelector(this.testHashesBatchedOperationsCorrectly.selector); + payloads[0] = abi.encodeWithSelector( + this.testHashesBatchedOperationsCorrectly.selector + ); + payloads[1] = abi.encodeWithSelector( + this.testHashesBatchedOperationsCorrectly.selector + ); bytes32 predecessor = NO_PREDECESSOR; bytes32 salt = EMPTY_SALT; - bytes32 hashedOperation = timelockController.hashOperationBatch(targets, values, payloads, predecessor, salt); - bytes32 expectedHash = keccak256(abi.encode(targets, values, payloads, predecessor, salt)); + bytes32 hashedOperation = timelockController.hashOperationBatch( + targets, + values, + payloads, + predecessor, + salt + ); + bytes32 expectedHash = keccak256( + abi.encode(targets, values, payloads, predecessor, salt) + ); assertEq(hashedOperation, expectedHash); } @@ -130,13 +217,23 @@ contract TimelockControllerTest is Test { function testUpdatesMinDelay() public { address target = address(timelockController); uint256 value = 0; - bytes memory data = abi.encodeWithSelector(timelockController.updateDelay.selector, MIN_DELAY); + bytes memory data = abi.encodeWithSelector( + timelockController.updateDelay.selector, + MIN_DELAY + ); bytes32 predecessor = NO_PREDECESSOR; bytes32 salt = EMPTY_SALT; vm.prank(PROPOSER_ONE); - timelockController.schedule(target, value, data, predecessor, salt, MIN_DELAY); + timelockController.schedule( + target, + value, + data, + predecessor, + salt, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY); @@ -150,14 +247,24 @@ contract TimelockControllerTest is Test { function testRevertWhenLessThanMinDelay() public { address target = address(timelockController); uint256 value = 0; - bytes memory data = abi.encodeWithSelector(timelockController.updateDelay.selector, 0); + bytes memory data = abi.encodeWithSelector( + timelockController.updateDelay.selector, + 0 + ); bytes32 predecessor = NO_PREDECESSOR; bytes32 salt = EMPTY_SALT; vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); - timelockController.schedule(target, value, data, predecessor, salt, MIN_DELAY - 1); + timelockController.schedule( + target, + value, + data, + predecessor, + salt, + MIN_DELAY - 1 + ); } function testUpdatesDelayAtLeastMinDelay() public { @@ -166,13 +273,23 @@ contract TimelockControllerTest is Test { address target = address(timelockController); uint256 value = 0; - bytes memory data = abi.encodeWithSelector(timelockController.updateDelay.selector, MIN_DELAY); + bytes memory data = abi.encodeWithSelector( + timelockController.updateDelay.selector, + MIN_DELAY + ); bytes32 predecessor = NO_PREDECESSOR; bytes32 salt = EMPTY_SALT; vm.prank(PROPOSER_ONE); - timelockController.schedule(target, value, data, NO_PREDECESSOR, EMPTY_SALT, 1); + timelockController.schedule( + target, + value, + data, + NO_PREDECESSOR, + EMPTY_SALT, + 1 + ); vm.warp(block.timestamp + 1); @@ -190,13 +307,24 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); } function _scheduleBatchedOperation() internal view - returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) + returns ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) { targets = new address[](calls.length); values = new uint256[](calls.length); @@ -210,30 +338,62 @@ contract TimelockControllerTest is Test { } function testProposerCanBatchSchedule() public { - (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleBatchedOperation(); - - bytes32 batchedOperationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) = _scheduleBatchedOperation(); + + bytes32 batchedOperationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); assertEq(timelockController.isOperation(batchedOperationID), false); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); assertEq(timelockController.isOperation(batchedOperationID), true); } function testAdminCantBatchSchedule() public { - (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleBatchedOperation(); - - bytes32 batchedOperationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) = _scheduleBatchedOperation(); + + bytes32 batchedOperationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); assertEq(timelockController.isOperation(batchedOperationID), false); vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); assertEq(timelockController.isOperation(batchedOperationID), false); } @@ -249,10 +409,24 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.startPrank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.expectRevert("TimelockController: operation already scheduled"); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); } function testRevertWhenScheduleIfDelayLessThanMinDelay() public { @@ -267,7 +441,14 @@ contract TimelockControllerTest is Test { vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY - 1); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY - 1 + ); } function testProposerCanScheduleOperation() public { @@ -281,7 +462,9 @@ contract TimelockControllerTest is Test { assertFalse(timelockController.isOperation(operationID)); } - function _scheduleOperation(address proposer) internal returns (bytes32 operationID) { + function _scheduleOperation( + address proposer + ) internal returns (bytes32 operationID) { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -292,8 +475,21 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.startPrank(proposer); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); - operationID = timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function _laterDelay() internal { @@ -322,10 +518,20 @@ contract TimelockControllerTest is Test { vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, 31 days - 1); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + 31 days - 1 + ); } - function _scheduleBatchedOperation(address proposer, uint256 delay) internal { + function _scheduleBatchedOperation( + address proposer, + uint256 delay + ) internal { address[] memory targets = new address[](calls.length); uint256[] memory values = new uint256[](calls.length); bytes[] memory payloads = new bytes[](calls.length); @@ -336,17 +542,31 @@ contract TimelockControllerTest is Test { payloads[i] = calls[i].data; } - bytes32 batchedOperationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 batchedOperationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); assertEq(timelockController.isOperation(batchedOperationID), false); vm.prank(proposer); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, delay); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + delay + ); assertEq(timelockController.isOperation(batchedOperationID), true); - uint256 operationTimestamp = timelockController.getTimestamp(batchedOperationID); + uint256 operationTimestamp = timelockController.getTimestamp( + batchedOperationID + ); assertEq(operationTimestamp, block.timestamp + delay); } @@ -368,20 +588,36 @@ contract TimelockControllerTest is Test { payloads[i] = calls[i].data; } - bytes32 batchedOperationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 batchedOperationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, 31 days); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + 31 days + ); - uint256 operationTimestampBefore = timelockController.getTimestamp(batchedOperationID); + uint256 operationTimestampBefore = timelockController.getTimestamp( + batchedOperationID + ); // Set a new delay value vm.prank(address(timelockController)); timelockController.updateDelay(31 days + 1); // New delay value should only apply on future operations, not existing ones - uint256 operationTimestampAfter = timelockController.getTimestamp(batchedOperationID); + uint256 operationTimestampAfter = timelockController.getTimestamp( + batchedOperationID + ); assertEq(operationTimestampAfter, operationTimestampBefore); } @@ -392,7 +628,13 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testRevertWhenMultipleOperationNotReady() public { @@ -407,13 +649,26 @@ contract TimelockControllerTest is Test { } vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY - 2 days); vm.expectRevert("TimelockController: operation is not ready"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testRevertWhenPredecessorOperationNotExecuted() public { @@ -429,19 +684,46 @@ contract TimelockControllerTest is Test { vm.startPrank(PROPOSER_ONE); // Schedule predecessor job - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); - bytes32 operationOneID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + bytes32 operationOneID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); // Schedule dependent job - timelockController.scheduleBatch(targets, values, payloads, operationOneID, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT, + MIN_DELAY + ); vm.stopPrank(); // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.expectRevert( + "TimelockController: predecessor operation is not done" + ); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, operationOneID, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT + ); } function testRevertWhenPredecessorOperationNotScheduled() public { @@ -457,18 +739,38 @@ contract TimelockControllerTest is Test { vm.startPrank(PROPOSER_ONE); // Prepare predecessor job - bytes32 operationOneID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationOneID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); // Schedule dependent job - timelockController.scheduleBatch(targets, values, payloads, operationOneID, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT, + MIN_DELAY + ); vm.stopPrank(); // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.expectRevert( + "TimelockController: predecessor operation is not done" + ); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, operationOneID, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT + ); } function testRevertWhenPredecessorOperationInvalid() public { @@ -486,13 +788,28 @@ contract TimelockControllerTest is Test { // Schedule dependent job vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, invalidPredecessor, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + invalidPredecessor, + EMPTY_SALT, + MIN_DELAY + ); // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.expectRevert( + "TimelockController: predecessor operation is not done" + ); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, invalidPredecessor, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + invalidPredecessor, + EMPTY_SALT + ); } function testRevertWhenOneTargetReverts() public { @@ -507,44 +824,95 @@ contract TimelockControllerTest is Test { // Schedule a job where one target will revert vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY + 2 days); vm.expectRevert("TimelockController: underlying transaction reverted"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testExecutorCanBatchExecuteOperation() public { - (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleSingleBatchedOperation(); + ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) = _scheduleSingleBatchedOperation(); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); - uint256 operationTimestamp = timelockController.getTimestamp(operationID); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + uint256 operationTimestamp = timelockController.getTimestamp( + operationID + ); assertEq(operationTimestamp, DONE_TIMESTAMP); } function testAdminCantBatchExecuteOperation() public { - (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _scheduleSingleBatchedOperation(); + ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) = _scheduleSingleBatchedOperation(); vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); - uint256 operationTimestamp = timelockController.getTimestamp(operationID); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + uint256 operationTimestamp = timelockController.getTimestamp( + operationID + ); assertEq(operationTimestamp, block.timestamp); } function _scheduleSingleBatchedOperation() internal - returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) + returns ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) { targets = new address[](1); targets[0] = address(counter); @@ -558,7 +926,14 @@ contract TimelockControllerTest is Test { vm.prank(PROPOSER_ONE); // Schedule batch executon - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY); } @@ -575,7 +950,13 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testRevertWhenSingleOperationNotReady() public { @@ -589,11 +970,24 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY - 2 days); vm.expectRevert("TimelockController: operation is not ready"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testRevertWhenPredecessorMultipleOperationNotExecuted() public { @@ -608,21 +1002,48 @@ contract TimelockControllerTest is Test { // Schedule predecessor job vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); - bytes32 operationOneID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + bytes32 operationOneID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); // Schedule dependent job vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, operationOneID, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT, + MIN_DELAY + ); // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: predecessor operation is not done"); + vm.expectRevert( + "TimelockController: predecessor operation is not done" + ); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, operationOneID, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT + ); } function testRevertWhenTargetReverts() public { @@ -638,24 +1059,54 @@ contract TimelockControllerTest is Test { vm.prank(PROPOSER_ONE); // Schedule predecessor job - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY + 2 days); vm.expectRevert("TimelockController: underlying transaction reverted"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testExecutorCanExecuteOperation() public { uint256 num = 10; - (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _executeOperation(num); + ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) = _executeOperation(num); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); - uint256 operationTimestamp = timelockController.getTimestamp(operationID); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + uint256 operationTimestamp = timelockController.getTimestamp( + operationID + ); assertEq(operationTimestamp, DONE_TIMESTAMP); uint256 counterNumber = counter.number(); assertEq(counterNumber, num); @@ -663,23 +1114,46 @@ contract TimelockControllerTest is Test { function testAdminCantExecuteOperation() public { uint256 num = 10; - (address[] memory targets, uint256[] memory values, bytes[] memory payloads) = _executeOperation(num); + ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) = _executeOperation(num); vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); - uint256 operationTimestamp = timelockController.getTimestamp(operationID); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + uint256 operationTimestamp = timelockController.getTimestamp( + operationID + ); assertEq(operationTimestamp, block.timestamp - MIN_DELAY); uint256 counterNumber = counter.number(); assertEq(counterNumber, 0); } - function _executeOperation(uint256 num) + function _executeOperation( + uint256 num + ) internal - returns (address[] memory targets, uint256[] memory values, bytes[] memory payloads) + returns ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) { targets = new address[](1); targets[0] = address(counter); @@ -691,12 +1165,25 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, num); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY + 2 days); } - event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data); + event CallExecuted( + bytes32 indexed id, + uint256 indexed index, + address target, + uint256 value, + bytes data + ); function testEmitsEvent() public { address[] memory targets = new address[](1); @@ -709,16 +1196,35 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY + 2 days); bytes32 predecessor = NO_PREDECESSOR; bytes32 salt = EMPTY_SALT; - bytes32 id = timelockController.hashOperationBatch(targets, values, payloads, predecessor, salt); + bytes32 id = timelockController.hashOperationBatch( + targets, + values, + payloads, + predecessor, + salt + ); vm.prank(EXECUTOR_ONE); vm.expectEmit(true, true, true, true); emit CallExecuted(id, 0, targets[0], values[0], payloads[0]); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testRevertWhenNonCanceller() public { @@ -738,20 +1244,38 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY + 1); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); vm.prank(PROPOSER_ONE); vm.expectRevert("TimelockController: operation cannot be cancelled"); timelockController.cancel(operationID); } function testCancellerCanCancelOperation() public { - (bytes32 operationID) = _cancelOperation(); + bytes32 operationID = _cancelOperation(); vm.prank(PROPOSER_ONE); timelockController.cancel(operationID); @@ -759,7 +1283,7 @@ contract TimelockControllerTest is Test { } function testAdminCanCancelOperation() public { - (bytes32 operationID) = _cancelOperation(); + bytes32 operationID = _cancelOperation(); vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); @@ -778,8 +1302,21 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); - operationID = timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } function testCanReceiveETH() public { @@ -804,10 +1341,22 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); bool isOperation = timelockController.isOperation(operationID); assertEq(isOperation, true); @@ -824,12 +1373,26 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bool isOperationPending = timelockController.isOperationPending(operationID); + bool isOperationPending = timelockController.isOperationPending( + operationID + ); assertEq(isOperationPending, true); } @@ -844,16 +1407,36 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bool isOperationPending = timelockController.isOperationPending(operationID); + bool isOperationPending = timelockController.isOperationPending( + operationID + ); assertEq(isOperationPending, false); } @@ -868,14 +1451,28 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bool isOperationReady = timelockController.isOperationReady(operationID); + bool isOperationReady = timelockController.isOperationReady( + operationID + ); assertEq(isOperationReady, true); } @@ -890,14 +1487,28 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY + 1 days); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bool isOperationReady = timelockController.isOperationReady(operationID); + bool isOperationReady = timelockController.isOperationReady( + operationID + ); assertEq(isOperationReady, true); } @@ -912,14 +1523,28 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY - 1 days); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bool isOperationReady = timelockController.isOperationReady(operationID); + bool isOperationReady = timelockController.isOperationReady( + operationID + ); assertEq(isOperationReady, false); } @@ -934,16 +1559,36 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bool isOperationReady = timelockController.isOperationReady(operationID); + bool isOperationReady = timelockController.isOperationReady( + operationID + ); assertEq(isOperationReady, false); } @@ -958,10 +1603,22 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); bool isOperationDone = timelockController.isOperationDone(operationID); assertEq(isOperationDone, false); @@ -978,20 +1635,40 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); bool isOperationDone = timelockController.isOperationDone(operationID); assertEq(isOperationDone, true); } - function testReturnsTheCorrectTimestampIfTheOperationHasNotBeenExecuted() public { + function testReturnsTheCorrectTimestampIfTheOperationHasNotBeenExecuted() + public + { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1002,12 +1679,26 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - uint256 operationTimestamp = timelockController.getTimestamp(operationID); + uint256 operationTimestamp = timelockController.getTimestamp( + operationID + ); assertEq(operationTimestamp, block.timestamp + MIN_DELAY); } @@ -1022,16 +1713,36 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY); + timelockController.scheduleBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + timelockController.executeBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 operationID = - timelockController.hashOperationBatch(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT); + bytes32 operationID = timelockController.hashOperationBatch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - uint256 operationTimestamp = timelockController.getTimestamp(operationID); + uint256 operationTimestamp = timelockController.getTimestamp( + operationID + ); assertEq(operationTimestamp, DONE_TIMESTAMP); } } @@ -1079,12 +1790,29 @@ contract TimelockControllerInvariants is Test { uint256 minDelay = 2 days; - bytes memory args = abi.encode(minDelay, proposers, executors, address(this)); - timelockController = - TimelockController(payable(vyperDeployer.deployContract("src/governance/", "TimelockController", args))); + bytes memory args = abi.encode( + minDelay, + proposers, + executors, + address(this) + ); + timelockController = TimelockController( + payable( + vyperDeployer.deployContract( + "src/governance/", + "TimelockController", + args + ) + ) + ); - timelockControllerHandler = - new TimelockControllerHandler(timelockController, minDelay, proposers, executors, address(this)); + timelockControllerHandler = new TimelockControllerHandler( + timelockController, + minDelay, + proposers, + executors, + address(this) + ); // Select the selectors to use for fuzzing. bytes4[] memory selectors = new bytes4[](3); @@ -1093,7 +1821,12 @@ contract TimelockControllerInvariants is Test { selectors[2] = TimelockControllerHandler.cancel.selector; // Set the target selector. - targetSelector(FuzzSelector({addr: address(timelockControllerHandler), selectors: selectors})); + targetSelector( + FuzzSelector({ + addr: address(timelockControllerHandler), + selectors: selectors + }) + ); // Set the target contract. targetContract(address(timelockControllerHandler)); @@ -1101,12 +1834,18 @@ contract TimelockControllerInvariants is Test { // Number of pending transactions cannot exceed executed transactions function invariantExecutedLessThanOrEqualToPending() public { - assertLe(timelockControllerHandler.execute_count(), timelockControllerHandler.schedule_count()); + assertLe( + timelockControllerHandler.execute_count(), + timelockControllerHandler.schedule_count() + ); } // Number of proposals executed must match the count number. function invariantProposalsExecutedMatchCount() public { - assertEq(timelockControllerHandler.execute_count(), timelockControllerHandler.counter()); + assertEq( + timelockControllerHandler.execute_count(), + timelockControllerHandler.counter() + ); } // Proposals can only be scheduled and executed once @@ -1119,7 +1858,9 @@ contract TimelockControllerInvariants is Test { timelockController.execute( address(timelockControllerHandler), 0, - abi.encodeWithSelector(TimelockControllerHandler.increment.selector), + abi.encodeWithSelector( + TimelockControllerHandler.increment.selector + ), bytes32(""), bytes32(executed[i]) ); @@ -1129,7 +1870,8 @@ contract TimelockControllerInvariants is Test { // Sum of number of executed proposals and cancelled proposals must be less or equal to the amount of proposals scheduled. function invariantSumOfProposals() public { assertLe( - timelockControllerHandler.cancel_count() + timelockControllerHandler.execute_count(), + timelockControllerHandler.cancel_count() + + timelockControllerHandler.execute_count(), timelockControllerHandler.schedule_count() ); } @@ -1140,7 +1882,9 @@ contract TimelockControllerInvariants is Test { // Loop over all executed proposals. for (uint256 i = 0; i < executed.length; ++i) { // Check that the executed proposal cannot be cancelled. - vm.expectRevert("TimelockController: operation cannot be cancelled"); + vm.expectRevert( + "TimelockController: operation cannot be cancelled" + ); timelockController.cancel(bytes32(executed[i])); } } @@ -1155,7 +1899,9 @@ contract TimelockControllerInvariants is Test { timelockController.execute( address(timelockControllerHandler), 0, - abi.encodeWithSelector(TimelockControllerHandler.increment.selector), + abi.encodeWithSelector( + TimelockControllerHandler.increment.selector + ), bytes32(""), bytes32(cancelled[i]) ); @@ -1172,7 +1918,9 @@ contract TimelockControllerInvariants is Test { timelockController.execute( address(timelockControllerHandler), 0, - abi.encodeWithSelector(TimelockControllerHandler.increment.selector), + abi.encodeWithSelector( + TimelockControllerHandler.increment.selector + ), bytes32(""), bytes32(pending[i]) ); @@ -1214,7 +1962,12 @@ contract TimelockControllerHandler is Test { function schedule(uint256 random) external { vm.prank(proposer); timelockController.schedule( - address(this), 0, abi.encodeWithSelector(this.increment.selector), bytes32(""), bytes32(random), minDelay + address(this), + 0, + abi.encodeWithSelector(this.increment.selector), + bytes32(""), + bytes32(random), + minDelay ); pending.push(random); @@ -1234,7 +1987,11 @@ contract TimelockControllerHandler is Test { vm.prank(executor); timelockController.execute( - address(this), 0, abi.encodeWithSelector(this.increment.selector), bytes32(""), bytes32(operation) + address(this), + 0, + abi.encodeWithSelector(this.increment.selector), + bytes32(""), + bytes32(operation) ); delete pending[identifier]; diff --git a/test/tokens/ERC1155.t.sol b/test/tokens/ERC1155.t.sol index 9c20735a..ac4ae342 100644 --- a/test/tokens/ERC1155.t.sol +++ b/test/tokens/ERC1155.t.sol @@ -30,38 +30,65 @@ contract ERC1155Test is Test { function setUp() public { bytes memory args = abi.encode(_BASE_URI); - ERC1155Extended = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); + ERC1155Extended = IERC1155Extended( + vyperDeployer.deployContract("src/tokens/", "ERC1155", args) + ); } function testInitialSetup() public { assertEq(ERC1155Extended.owner(), deployer); assertTrue(ERC1155Extended.is_minter(deployer)); - assertEq(ERC1155Extended.uri(0), string.concat(_BASE_URI, Strings.toString(uint256(0)))); - assertEq(ERC1155Extended.uri(1), string.concat(_BASE_URI, Strings.toString(uint256(1)))); + assertEq( + ERC1155Extended.uri(0), + string.concat(_BASE_URI, Strings.toString(uint256(0))) + ); + assertEq( + ERC1155Extended.uri(1), + string.concat(_BASE_URI, Strings.toString(uint256(1))) + ); vm.expectEmit(true, true, false, false); emit IERC1155Extended.OwnershipTransferred(zeroAddress, deployer); vm.expectEmit(true, false, false, true); emit IERC1155Extended.RoleMinterChanged(deployer, true); bytes memory args = abi.encode(_BASE_URI); - ERC1155ExtendedInitialEvent = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); + ERC1155ExtendedInitialEvent = IERC1155Extended( + vyperDeployer.deployContract("src/tokens/", "ERC1155", args) + ); assertEq(ERC1155ExtendedInitialEvent.owner(), deployer); assertTrue(ERC1155ExtendedInitialEvent.is_minter(deployer)); - assertEq(ERC1155ExtendedInitialEvent.uri(0), string.concat(_BASE_URI, Strings.toString(uint256(0)))); - assertEq(ERC1155ExtendedInitialEvent.uri(1), string.concat(_BASE_URI, Strings.toString(uint256(1)))); + assertEq( + ERC1155ExtendedInitialEvent.uri(0), + string.concat(_BASE_URI, Strings.toString(uint256(0))) + ); + assertEq( + ERC1155ExtendedInitialEvent.uri(1), + string.concat(_BASE_URI, Strings.toString(uint256(1))) + ); } function testSupportsInterfaceSuccess() public { - assertTrue(ERC1155Extended.supportsInterface(type(IERC165).interfaceId)); - assertTrue(ERC1155Extended.supportsInterface(type(IERC1155).interfaceId)); - assertTrue(ERC1155Extended.supportsInterface(type(IERC1155MetadataURI).interfaceId)); + assertTrue( + ERC1155Extended.supportsInterface(type(IERC165).interfaceId) + ); + assertTrue( + ERC1155Extended.supportsInterface(type(IERC1155).interfaceId) + ); + assertTrue( + ERC1155Extended.supportsInterface( + type(IERC1155MetadataURI).interfaceId + ) + ); } function testSupportsInterfaceSuccessGasCost() public { uint256 startGas = gasleft(); ERC1155Extended.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && ERC1155Extended.supportsInterface(type(IERC165).interfaceId)); + assertTrue( + gasUsed <= 30_000 && + ERC1155Extended.supportsInterface(type(IERC165).interfaceId) + ); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -72,7 +99,9 @@ contract ERC1155Test is Test { uint256 startGas = gasleft(); ERC1155Extended.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && !ERC1155Extended.supportsInterface(0x0011bbff)); + assertTrue( + gasUsed <= 30_000 && !ERC1155Extended.supportsInterface(0x0011bbff) + ); } function testBalanceOfCase1() public { @@ -87,7 +116,10 @@ contract ERC1155Test is Test { ERC1155Extended.safe_mint(firstOwner, id1, amountFirstOwner, data); ERC1155Extended.safe_mint(secondOwner, id2, amountSecondOwner, data); assertEq(ERC1155Extended.balanceOf(firstOwner, id1), amountFirstOwner); - assertEq(ERC1155Extended.balanceOf(secondOwner, id2), amountSecondOwner); + assertEq( + ERC1155Extended.balanceOf(secondOwner, id2), + amountSecondOwner + ); assertEq(ERC1155Extended.balanceOf(firstOwner, 2), 0); vm.stopPrank(); } @@ -352,17 +384,27 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); + vm.expectRevert( + bytes("ERC1155: caller is not token owner or approved") + ); ERC1155Extended.safeTransferFrom(owner, receiver, id1, amount1, data); vm.stopPrank(); } function testSafeTransferFromNoData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -411,10 +453,18 @@ contract ERC1155Test is Test { function testSafeTransferFromWithData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -464,9 +514,15 @@ contract ERC1155Test is Test { function testSafeTransferFromReceiverInvalidReturnIdentifier() public { address owner = makeAddr("owner"); bytes4 receiverSingleMagicValue = 0x00bb8833; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -479,7 +535,9 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); + vm.expectRevert( + bytes("ERC1155: transfer to non-ERC1155Receiver implementer") + ); ERC1155Extended.safeTransferFrom(owner, receiver, id1, amount1, data); vm.stopPrank(); @@ -492,17 +550,27 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); + vm.expectRevert( + bytes("ERC1155: transfer to non-ERC1155Receiver implementer") + ); ERC1155Extended.safeTransferFrom(owner, receiver, id2, amount2, data); vm.stopPrank(); } function testSafeTransferFromReceiverReverts() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + true, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -575,7 +643,13 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC1155: insufficient balance for transfer")); - ERC1155Extended.safeTransferFrom(owner, makeAddr("to"), id, ++amount, data); + ERC1155Extended.safeTransferFrom( + owner, + makeAddr("to"), + id, + ++amount, + data + ); vm.stopPrank(); } @@ -617,7 +691,13 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -656,7 +736,13 @@ contract ERC1155Test is Test { vm.startPrank(operator); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(operator, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -687,17 +773,33 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + vm.expectRevert( + bytes("ERC1155: caller is not token owner or approved") + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); vm.stopPrank(); } function testSafeBatchTransferFromNoData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -720,8 +822,20 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + emit ERC1155ReceiverMock.BatchReceived( + owner, + owner, + ids, + amounts, + data + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -731,10 +845,18 @@ contract ERC1155Test is Test { function testSafeBatchTransferFromWithData() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -757,8 +879,20 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + emit ERC1155ReceiverMock.BatchReceived( + owner, + owner, + ids, + amounts, + data + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -768,10 +902,16 @@ contract ERC1155Test is Test { function testSafeBatchTransferFromReceiverInvalidReturnIdentifier() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -791,17 +931,31 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + vm.expectRevert( + bytes("ERC1155: transfer to non-ERC1155Receiver implementer") + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); vm.stopPrank(); } function testSafeBatchTransferFromReceiverReverts() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, true); + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + true + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -821,8 +975,16 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert(bytes("ERC1155ReceiverMock: reverting on batch receive")); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + vm.expectRevert( + bytes("ERC1155ReceiverMock: reverting on batch receive") + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); vm.stopPrank(); } @@ -847,16 +1009,30 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(); - ERC1155Extended.safeBatchTransferFrom(owner, deployer, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + deployer, + ids, + amounts, + data + ); vm.stopPrank(); } function testSafeBatchTransferFromReceiverRevertsOnlySingle() public { address owner = makeAddr("owner"); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + true, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -879,8 +1055,20 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + emit ERC1155ReceiverMock.BatchReceived( + owner, + owner, + ids, + amounts, + data + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -910,7 +1098,13 @@ contract ERC1155Test is Test { vm.startPrank(owner); ++amounts[3]; vm.expectRevert(bytes("ERC1155: insufficient balance for transfer")); - ERC1155Extended.safeBatchTransferFrom(owner, makeAddr("to"), ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + makeAddr("to"), + ids, + amounts, + data + ); vm.stopPrank(); } @@ -940,9 +1134,21 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC1155: ids and amounts length mismatch")); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids1, amounts1, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids1, + amounts1, + data + ); vm.expectRevert(bytes("ERC1155: ids and amounts length mismatch")); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids2, amounts2, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids2, + amounts2, + data + ); vm.stopPrank(); } @@ -967,18 +1173,32 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC1155: transfer to the zero address")); - ERC1155Extended.safeBatchTransferFrom(owner, zeroAddress, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + zeroAddress, + ids, + amounts, + data + ); vm.stopPrank(); } function testUriNoTokenUri() public { - assertEq(ERC1155Extended.uri(0), string.concat(_BASE_URI, Strings.toString(uint256(0)))); - assertEq(ERC1155Extended.uri(1), string.concat(_BASE_URI, Strings.toString(uint256(1)))); + assertEq( + ERC1155Extended.uri(0), + string.concat(_BASE_URI, Strings.toString(uint256(0))) + ); + assertEq( + ERC1155Extended.uri(1), + string.concat(_BASE_URI, Strings.toString(uint256(1))) + ); } function testUriNoBaseURI() public { bytes memory args = abi.encode(""); - ERC1155ExtendedNoBaseURI = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); + ERC1155ExtendedNoBaseURI = IERC1155Extended( + vyperDeployer.deployContract("src/tokens/", "ERC1155", args) + ); string memory uri = "my_awesome_uri"; uint256 id = 1; vm.prank(deployer); @@ -996,7 +1216,9 @@ contract ERC1155Test is Test { function testUriBaseAndTokenUriNotSet() public { bytes memory args = abi.encode(""); - ERC1155ExtendedNoBaseURI = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); + ERC1155ExtendedNoBaseURI = IERC1155Extended( + vyperDeployer.deployContract("src/tokens/", "ERC1155", args) + ); uint256 id = 1; assertEq(ERC1155ExtendedNoBaseURI.uri(id), ""); } @@ -1016,9 +1238,15 @@ contract ERC1155Test is Test { uint256 id = 1; vm.prank(deployer); vm.expectEmit(true, false, false, true); - emit IERC1155.URI(string.concat(_BASE_URI, Strings.toString(uint256(id))), id); + emit IERC1155.URI( + string.concat(_BASE_URI, Strings.toString(uint256(id))), + id + ); ERC1155Extended.set_uri(id, uri); - assertEq(ERC1155Extended.uri(id), string.concat(_BASE_URI, Strings.toString(uint256(id)))); + assertEq( + ERC1155Extended.uri(id), + string.concat(_BASE_URI, Strings.toString(uint256(id))) + ); } function testSetUriNonMinter() public { @@ -1055,7 +1283,12 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch(makeAddr("owner"), ids, amounts, new bytes(0)); + ERC1155Extended.safe_mint_batch( + makeAddr("owner"), + ids, + amounts, + new bytes(0) + ); assertEq(ERC1155Extended.total_supply(0), 11); assertEq(ERC1155Extended.total_supply(1), 22); vm.stopPrank(); @@ -1130,7 +1363,12 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch(makeAddr("owner"), ids, amounts, new bytes(0)); + ERC1155Extended.safe_mint_batch( + makeAddr("owner"), + ids, + amounts, + new bytes(0) + ); assertTrue(ERC1155Extended.exists(0)); assertTrue(ERC1155Extended.exists(1)); vm.stopPrank(); @@ -1191,7 +1429,13 @@ contract ERC1155Test is Test { vm.startPrank(firstOwner); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(firstOwner, firstOwner, zeroAddress, id, burnAmount); + emit IERC1155.TransferSingle( + firstOwner, + firstOwner, + zeroAddress, + id, + burnAmount + ); ERC1155Extended.burn(firstOwner, id, 10); assertEq(ERC1155Extended.total_supply(0), 25); assertEq(ERC1155Extended.balanceOf(firstOwner, id), 5); @@ -1222,7 +1466,13 @@ contract ERC1155Test is Test { vm.startPrank(operator); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(operator, owner, zeroAddress, id1, burnAmount); + emit IERC1155.TransferSingle( + operator, + owner, + zeroAddress, + id1, + burnAmount + ); ERC1155Extended.burn(owner, id1, burnAmount); assertEq(ERC1155Extended.total_supply(id1), amount1 - burnAmount); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1248,7 +1498,9 @@ contract ERC1155Test is Test { vm.stopPrank(); vm.startPrank(operator); - vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); + vm.expectRevert( + bytes("ERC1155: caller is not token owner or approved") + ); ERC1155Extended.burn(owner, id1, burnAmount); vm.stopPrank(); } @@ -1376,7 +1628,9 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(operator); - vm.expectRevert(bytes("ERC1155: caller is not token owner or approved")); + vm.expectRevert( + bytes("ERC1155: caller is not token owner or approved") + ); ERC1155Extended.burn_batch(owner, ids, amounts); vm.stopPrank(); } @@ -1483,11 +1737,23 @@ contract ERC1155Test is Test { bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id1, + amount1 + ); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id2, + amount2 + ); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1497,10 +1763,18 @@ contract ERC1155Test is Test { } function testSafeMintNoData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1509,11 +1783,23 @@ contract ERC1155Test is Test { bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id1, + amount1 + ); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id2, + amount2 + ); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1523,10 +1809,18 @@ contract ERC1155Test is Test { } function testSafeMintWithData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1535,11 +1829,23 @@ contract ERC1155Test is Test { bytes memory data = new bytes(42); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id1, + amount1 + ); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id2, + amount2 + ); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -1550,9 +1856,15 @@ contract ERC1155Test is Test { function testSafeMintReceiverInvalidReturnIdentifier() public { bytes4 receiverSingleMagicValue = 0x00bb8833; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1560,19 +1872,31 @@ contract ERC1155Test is Test { uint256 amount2 = 15; bytes memory data = new bytes(0); vm.startPrank(deployer); - vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); + vm.expectRevert( + bytes("ERC1155: transfer to non-ERC1155Receiver implementer") + ); ERC1155Extended.safe_mint(receiver, id1, amount1, data); - vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); + vm.expectRevert( + bytes("ERC1155: transfer to non-ERC1155Receiver implementer") + ); ERC1155Extended.safe_mint(receiver, id2, amount2, data); vm.stopPrank(); } function testSafeMintReceiverReverts() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + true, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256 id1 = 1; uint256 amount1 = 1; @@ -1642,7 +1966,13 @@ contract ERC1155Test is Test { bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id, amount); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id, + amount + ); ERC1155Extended.safe_mint(receiver, id, amount, data); vm.expectRevert(); @@ -1667,7 +1997,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -1677,10 +2013,18 @@ contract ERC1155Test is Test { } function testSafeMintBatchNoData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -1697,7 +2041,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -1707,10 +2057,18 @@ contract ERC1155Test is Test { } function testSafeMintBatchWithData() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -1727,7 +2085,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -1737,10 +2101,16 @@ contract ERC1155Test is Test { } function testSafeMintBatchReceiverInvalidReturnIdentifier() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -1756,16 +2126,24 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - vm.expectRevert(bytes("ERC1155: transfer to non-ERC1155Receiver implementer")); + vm.expectRevert( + bytes("ERC1155: transfer to non-ERC1155Receiver implementer") + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); vm.stopPrank(); } function testSafeMintBatchReceiverReverts() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; bytes4 receiverBatchMagicValue = 0x00bb8833; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, true); + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + true + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -1781,7 +2159,9 @@ contract ERC1155Test is Test { amounts[3] = 20; vm.startPrank(deployer); - vm.expectRevert(bytes("ERC1155ReceiverMock: reverting on batch receive")); + vm.expectRevert( + bytes("ERC1155ReceiverMock: reverting on batch receive") + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); vm.stopPrank(); } @@ -1807,10 +2187,18 @@ contract ERC1155Test is Test { } function testSafeMintBatchReceiverRevertsOnlySingle() public { - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, true, receiverBatchMagicValue, false); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + true, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](4); uint256[] memory amounts = new uint256[](4); @@ -1827,7 +2215,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -1924,7 +2318,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); vm.expectRevert(); @@ -2016,7 +2416,10 @@ contract ERC1155Test is Test { ERC1155Extended.renounce_ownership(); } - function testFuzzSetApprovalForAllSuccess(address owner, address operator) public { + function testFuzzSetApprovalForAllSuccess( + address owner, + address operator + ) public { vm.assume(owner != operator); bool approved = true; assertTrue(!ERC1155Extended.isApprovedForAll(owner, operator)); @@ -2033,7 +2436,10 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSetApprovalForAllRevoke(address owner, address operator) public { + function testFuzzSetApprovalForAllRevoke( + address owner, + address operator + ) public { vm.assume(owner != operator); bool approved = true; assertTrue(!ERC1155Extended.isApprovedForAll(owner, operator)); @@ -2060,8 +2466,11 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress - && receiver.code.length == 0 + owner != zeroAddress && + owner != receiver && + owner.code.length == 0 && + receiver != zeroAddress && + receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); vm.startPrank(deployer); @@ -2091,8 +2500,14 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && owner != receiver && owner != operator && owner.code.length == 0 - && receiver != operator && receiver != zeroAddress && operator != zeroAddress && receiver.code.length == 0 + owner != zeroAddress && + owner != receiver && + owner != operator && + owner.code.length == 0 && + receiver != operator && + receiver != zeroAddress && + operator != zeroAddress && + receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); bool approved = true; @@ -2120,14 +2535,32 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeTransferFromNoData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) - public - { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + function testFuzzSafeTransferFromNoData( + address owner, + uint256 id1, + uint256 amount1, + uint256 id2, + uint256 amount2 + ) public { + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); bytes memory data = new bytes(0); @@ -2180,11 +2613,25 @@ contract ERC1155Test is Test { uint256 amount2, bytes calldata data ) public { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); vm.startPrank(deployer); @@ -2238,8 +2685,11 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress - && receiver.code.length == 0 + owner != zeroAddress && + owner != receiver && + owner.code.length == 0 && + receiver != zeroAddress && + receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); uint256[] memory ids = new uint256[](2); @@ -2256,7 +2706,13 @@ contract ERC1155Test is Test { vm.startPrank(owner); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2275,8 +2731,14 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && owner != receiver && owner != operator && owner.code.length == 0 - && receiver != operator && receiver != zeroAddress && operator != zeroAddress && receiver.code.length == 0 + owner != zeroAddress && + owner != receiver && + owner != operator && + owner.code.length == 0 && + receiver != operator && + receiver != zeroAddress && + operator != zeroAddress && + receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); bool approved = true; @@ -2301,7 +2763,13 @@ contract ERC1155Test is Test { vm.startPrank(operator); vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(operator, owner, receiver, ids, amounts); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2317,11 +2785,25 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); uint256[] memory ids = new uint256[](2); @@ -2341,8 +2823,20 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + emit ERC1155ReceiverMock.BatchReceived( + owner, + owner, + ids, + amounts, + data + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2357,11 +2851,25 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); vm.assume(owner != receiver); /** @@ -2385,8 +2893,20 @@ contract ERC1155Test is Test { vm.expectEmit(true, true, true, true); emit IERC1155.TransferBatch(owner, owner, receiver, ids, amounts); vm.expectEmit(true, true, false, true, receiver); - emit ERC1155ReceiverMock.BatchReceived(owner, owner, ids, amounts, data); - ERC1155Extended.safeBatchTransferFrom(owner, receiver, ids, amounts, data); + emit ERC1155ReceiverMock.BatchReceived( + owner, + owner, + ids, + amounts, + data + ); + ERC1155Extended.safeBatchTransferFrom( + owner, + receiver, + ids, + amounts, + data + ); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.balanceOf(owner, ids[i]), 0); assertEq(ERC1155Extended.balanceOf(receiver, ids[i]), amounts[i]); @@ -2401,10 +2921,19 @@ contract ERC1155Test is Test { ERC1155Extended.set_uri(1, "my_awesome_uri"); } - function testFuzzTotalSupplyAfterSingleMint(uint256 id, uint256 amount, bytes calldata data) public { + function testFuzzTotalSupplyAfterSingleMint( + uint256 id, + uint256 amount, + bytes calldata data + ) public { vm.startPrank(deployer); ERC1155Extended.safe_mint(makeAddr("firstOwner"), id, amount % 2, data); - ERC1155Extended.safe_mint(makeAddr("secondOwner"), id, amount % 2, data); + ERC1155Extended.safe_mint( + makeAddr("secondOwner"), + id, + amount % 2, + data + ); assertEq(ERC1155Extended.total_supply(id), 2 * (amount % 2)); vm.stopPrank(); } @@ -2416,7 +2945,13 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -2426,14 +2961,28 @@ contract ERC1155Test is Test { amounts[1] = amount2; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch(owner, ids, amounts, new bytes(id2 % 2)); + ERC1155Extended.safe_mint_batch( + owner, + ids, + amounts, + new bytes(id2 % 2) + ); assertEq(ERC1155Extended.total_supply(ids[0]), amounts[0]); assertEq(ERC1155Extended.total_supply(ids[1]), amounts[1]); vm.stopPrank(); } - function testFuzzTotalSupplyAfterSingleBurn(address owner, uint256 id, bytes calldata data) public { - vm.assume(owner != zeroAddress && owner != makeAddr("secondOwner") && owner.code.length == 0 && id > 0); + function testFuzzTotalSupplyAfterSingleBurn( + address owner, + uint256 id, + bytes calldata data + ) public { + vm.assume( + owner != zeroAddress && + owner != makeAddr("secondOwner") && + owner.code.length == 0 && + id > 0 + ); vm.startPrank(deployer); ERC1155Extended.safe_mint(owner, id, 15, data); ERC1155Extended.safe_mint(makeAddr("secondOwner"), id, 20, data); @@ -2452,7 +3001,13 @@ contract ERC1155Test is Test { uint256 id2, uint256 amount2 ) public { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -2462,7 +3017,12 @@ contract ERC1155Test is Test { amounts[1] = amount2; vm.startPrank(deployer); - ERC1155Extended.safe_mint_batch(owner, ids, amounts, new bytes(id2 % 2)); + ERC1155Extended.safe_mint_batch( + owner, + ids, + amounts, + new bytes(id2 % 2) + ); vm.stopPrank(); vm.startPrank(owner); @@ -2472,10 +3032,17 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzBurnSuccess(address firstOwner, address secondOwner, uint256 id) public { + function testFuzzBurnSuccess( + address firstOwner, + address secondOwner, + uint256 id + ) public { vm.assume( - firstOwner != zeroAddress && firstOwner.code.length == 0 && firstOwner != secondOwner - && secondOwner != zeroAddress && secondOwner.code.length == 0 + firstOwner != zeroAddress && + firstOwner.code.length == 0 && + firstOwner != secondOwner && + secondOwner != zeroAddress && + secondOwner.code.length == 0 ); uint256 burnAmount = 10; bytes memory data = new bytes(0); @@ -2486,7 +3053,13 @@ contract ERC1155Test is Test { vm.startPrank(firstOwner); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(firstOwner, firstOwner, zeroAddress, id, burnAmount); + emit IERC1155.TransferSingle( + firstOwner, + firstOwner, + zeroAddress, + id, + burnAmount + ); ERC1155Extended.burn(firstOwner, id, 10); assertEq(ERC1155Extended.total_supply(id), 25); assertEq(ERC1155Extended.balanceOf(firstOwner, id), 5); @@ -2494,10 +3067,20 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzBurnBatchSuccess(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) - public - { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); + function testFuzzBurnBatchSuccess( + address owner, + uint256 id1, + uint256 amount1, + uint256 id2, + uint256 amount2 + ) public { + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); bytes memory data = new bytes(id2 % 2); @@ -2532,17 +3115,32 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress - && receiver.code.length == 0 + owner != zeroAddress && + owner != receiver && + owner.code.length == 0 && + receiver != zeroAddress && + receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id1, + amount1 + ); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id2, + amount2 + ); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -2551,21 +3149,53 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeMintNoData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) public { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + function testFuzzSafeMintNoData( + address owner, + uint256 id1, + uint256 amount1, + uint256 id2, + uint256 amount2 + ) public { + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); bytes memory data = new bytes(0); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id1, + amount1 + ); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id2, + amount2 + ); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -2582,19 +3212,45 @@ contract ERC1155Test is Test { uint256 amount2, bytes calldata data ) public { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id1, amount1); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id1, + amount1 + ); ERC1155Extended.safe_mint(receiver, id1, amount1, data); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferSingle(deployer, zeroAddress, receiver, id2, amount2); + emit IERC1155.TransferSingle( + deployer, + zeroAddress, + receiver, + id2, + amount2 + ); ERC1155Extended.safe_mint(receiver, id2, amount2, data); assertEq(ERC1155Extended.total_supply(id1), amount1); assertEq(ERC1155Extended.total_supply(id2), amount2); @@ -2630,8 +3286,11 @@ contract ERC1155Test is Test { bytes calldata data ) public { vm.assume( - owner != zeroAddress && owner != receiver && owner.code.length == 0 && receiver != zeroAddress - && receiver.code.length == 0 + owner != zeroAddress && + owner != receiver && + owner.code.length == 0 && + receiver != zeroAddress && + receiver.code.length == 0 ); vm.assume(id1 != id2 && amount1 > 0 && amount2 > 0); uint256[] memory ids = new uint256[](2); @@ -2644,7 +3303,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -2653,14 +3318,32 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeMintBatchNoData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) - public - { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + function testFuzzSafeMintBatchNoData( + address owner, + uint256 id1, + uint256 amount1, + uint256 id2, + uint256 amount2 + ) public { + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -2673,7 +3356,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -2682,14 +3371,32 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSafeMintBatchWithData(address owner, uint256 id1, uint256 amount1, uint256 id2, uint256 amount2) - public - { - vm.assume(owner != zeroAddress && owner.code.length == 0 && id1 != id2 && amount1 > 0 && amount2 > 0); - bytes4 receiverSingleMagicValue = IERC1155Receiver.onERC1155Received.selector; - bytes4 receiverBatchMagicValue = IERC1155Receiver.onERC1155BatchReceived.selector; - ERC1155ReceiverMock erc1155ReceiverMock = - new ERC1155ReceiverMock(receiverSingleMagicValue, false, receiverBatchMagicValue, false); + function testFuzzSafeMintBatchWithData( + address owner, + uint256 id1, + uint256 amount1, + uint256 id2, + uint256 amount2 + ) public { + vm.assume( + owner != zeroAddress && + owner.code.length == 0 && + id1 != id2 && + amount1 > 0 && + amount2 > 0 + ); + bytes4 receiverSingleMagicValue = IERC1155Receiver + .onERC1155Received + .selector; + bytes4 receiverBatchMagicValue = IERC1155Receiver + .onERC1155BatchReceived + .selector; + ERC1155ReceiverMock erc1155ReceiverMock = new ERC1155ReceiverMock( + receiverSingleMagicValue, + false, + receiverBatchMagicValue, + false + ); address receiver = address(erc1155ReceiverMock); uint256[] memory ids = new uint256[](2); uint256[] memory amounts = new uint256[](2); @@ -2706,7 +3413,13 @@ contract ERC1155Test is Test { vm.startPrank(deployer); vm.expectEmit(true, true, true, true); - emit IERC1155.TransferBatch(deployer, zeroAddress, receiver, ids, amounts); + emit IERC1155.TransferBatch( + deployer, + zeroAddress, + receiver, + ids, + amounts + ); ERC1155Extended.safe_mint_batch(receiver, ids, amounts, data); for (uint256 i; i < ids.length; ++i) { assertEq(ERC1155Extended.total_supply(ids[i]), amounts[i]); @@ -2752,15 +3465,24 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzSetMinterNonOwner(address msgSender, string calldata minter) public { + function testFuzzSetMinterNonOwner( + address msgSender, + string calldata minter + ) public { vm.assume(msgSender != deployer); vm.expectRevert(bytes("Ownable: caller is not the owner")); ERC1155Extended.set_minter(makeAddr(minter), true); } - function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { + function testFuzzTransferOwnershipSuccess( + address newOwner1, + address newOwner2 + ) public { vm.assume( - newOwner1 != zeroAddress && newOwner1 != deployer && newOwner1 != newOwner2 && newOwner2 != zeroAddress + newOwner1 != zeroAddress && + newOwner1 != deployer && + newOwner1 != newOwner2 && + newOwner2 != zeroAddress ); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -2791,7 +3513,10 @@ contract ERC1155Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { + function testFuzzTransferOwnershipNonOwner( + address nonOwner, + address newOwner + ) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -2843,7 +3568,9 @@ contract ERC1155Invariants is Test { function setUp() public { bytes memory args = abi.encode(_BASE_URI); - ERC1155Extended = IERC1155Extended(vyperDeployer.deployContract("src/tokens/", "ERC1155", args)); + ERC1155Extended = IERC1155Extended( + vyperDeployer.deployContract("src/tokens/", "ERC1155", args) + ); erc1155Handler = new ERC1155Handler(ERC1155Extended, deployer); targetContract(address(erc1155Handler)); targetSender(deployer); @@ -2870,7 +3597,13 @@ contract ERC1155Handler { token.setApprovalForAll(operator, approved); } - function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) public { + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes calldata data + ) public { token.safeTransferFrom(from, to, id, amount, data); } @@ -2888,17 +3621,29 @@ contract ERC1155Handler { token.burn(ownerAddr, id, amount); } - function burn_batch(address ownerAddr, uint256[] calldata ids, uint256[] calldata amounts) public { + function burn_batch( + address ownerAddr, + uint256[] calldata ids, + uint256[] calldata amounts + ) public { token.burn_batch(ownerAddr, ids, amounts); } - function safe_mint(address ownerAddr, uint256 id, uint256 amount, bytes calldata data) public { + function safe_mint( + address ownerAddr, + uint256 id, + uint256 amount, + bytes calldata data + ) public { token.safe_mint(ownerAddr, id, amount, data); } - function safe_mint_batch(address ownerAddr, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) - public - { + function safe_mint_batch( + address ownerAddr, + uint256[] calldata ids, + uint256[] calldata amounts, + bytes calldata data + ) public { token.safe_mint_batch(ownerAddr, ids, amounts, data); } diff --git a/test/tokens/ERC20.t.sol b/test/tokens/ERC20.t.sol index 0c229430..56e02b2d 100644 --- a/test/tokens/ERC20.t.sol +++ b/test/tokens/ERC20.t.sol @@ -15,9 +15,17 @@ contract ERC20Test is Test { string private constant _VERSION_EIP712 = "1"; uint256 private constant _INITIAL_SUPPLY = type(uint8).max; bytes32 private constant _TYPE_HASH = - keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); + keccak256( + bytes( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ) + ); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256(bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")); + keccak256( + bytes( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ) + ); VyperDeployer private vyperDeployer = new VyperDeployer(); @@ -34,8 +42,16 @@ contract ERC20Test is Test { address private ERC20ExtendedAddr; function setUp() public { - bytes memory args = abi.encode(_NAME, _SYMBOL, _INITIAL_SUPPLY, _NAME_EIP712, _VERSION_EIP712); - ERC20Extended = IERC20Extended(vyperDeployer.deployContract("src/tokens/", "ERC20", args)); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + _INITIAL_SUPPLY, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC20Extended = IERC20Extended( + vyperDeployer.deployContract("src/tokens/", "ERC20", args) + ); ERC20ExtendedAddr = address(ERC20Extended); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( @@ -54,7 +70,10 @@ contract ERC20Test is Test { assertEq(ERC20Extended.name(), _NAME); assertEq(ERC20Extended.symbol(), _SYMBOL); assertEq(ERC20Extended.totalSupply(), _INITIAL_SUPPLY * multiplier); - assertEq(ERC20Extended.balanceOf(deployer), _INITIAL_SUPPLY * multiplier); + assertEq( + ERC20Extended.balanceOf(deployer), + _INITIAL_SUPPLY * multiplier + ); assertEq(ERC20Extended.owner(), deployer); assertTrue(ERC20Extended.is_minter(deployer)); @@ -63,14 +82,32 @@ contract ERC20Test is Test { vm.expectEmit(true, false, false, true); emit IERC20Extended.RoleMinterChanged(deployer, true); vm.expectEmit(true, true, false, true); - emit IERC20.Transfer(zeroAddress, deployer, _INITIAL_SUPPLY * multiplier); - bytes memory args = abi.encode(_NAME, _SYMBOL, _INITIAL_SUPPLY, _NAME_EIP712, _VERSION_EIP712); - ERC20ExtendedInitialEvent = IERC20Extended(vyperDeployer.deployContract("src/tokens/", "ERC20", args)); + emit IERC20.Transfer( + zeroAddress, + deployer, + _INITIAL_SUPPLY * multiplier + ); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + _INITIAL_SUPPLY, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC20ExtendedInitialEvent = IERC20Extended( + vyperDeployer.deployContract("src/tokens/", "ERC20", args) + ); assertEq(ERC20ExtendedInitialEvent.decimals(), 18); assertEq(ERC20ExtendedInitialEvent.name(), _NAME); assertEq(ERC20ExtendedInitialEvent.symbol(), _SYMBOL); - assertEq(ERC20ExtendedInitialEvent.totalSupply(), _INITIAL_SUPPLY * multiplier); - assertEq(ERC20ExtendedInitialEvent.balanceOf(deployer), _INITIAL_SUPPLY * multiplier); + assertEq( + ERC20ExtendedInitialEvent.totalSupply(), + _INITIAL_SUPPLY * multiplier + ); + assertEq( + ERC20ExtendedInitialEvent.balanceOf(deployer), + _INITIAL_SUPPLY * multiplier + ); assertEq(ERC20ExtendedInitialEvent.owner(), deployer); assertTrue(ERC20ExtendedInitialEvent.is_minter(deployer)); } @@ -82,7 +119,10 @@ contract ERC20Test is Test { function testBalanceOf() public { uint256 multiplier = 10 ** uint256(ERC20Extended.decimals()); - assertEq(ERC20Extended.balanceOf(deployer), _INITIAL_SUPPLY * multiplier); + assertEq( + ERC20Extended.balanceOf(deployer), + _INITIAL_SUPPLY * multiplier + ); assertEq(ERC20Extended.balanceOf(makeAddr("account")), 0); } @@ -228,7 +268,11 @@ contract ERC20Test is Test { ERC20Extended.approve(spender, amount); vm.startPrank(spender); vm.expectEmit(true, true, false, true); - emit IERC20.Approval(owner, spender, ERC20Extended.allowance(owner, spender) - amount); + emit IERC20.Approval( + owner, + spender, + ERC20Extended.allowance(owner, spender) - amount + ); vm.expectEmit(true, true, false, true); emit IERC20.Transfer(owner, to, amount); bool returnValue = ERC20Extended.transferFrom(owner, to, amount); @@ -361,7 +405,11 @@ contract ERC20Test is Test { ERC20Extended.approve(spender, amount); vm.startPrank(spender); vm.expectEmit(true, true, false, true); - emit IERC20.Approval(owner, spender, ERC20Extended.allowance(owner, spender) - amount); + emit IERC20.Approval( + owner, + spender, + ERC20Extended.allowance(owner, spender) - amount + ); vm.expectEmit(true, true, false, true); emit IERC20.Transfer(owner, zeroAddress, amount); @@ -382,7 +430,11 @@ contract ERC20Test is Test { ERC20Extended.approve(spender, balance); vm.startPrank(spender); vm.expectEmit(true, true, false, true); - emit IERC20.Approval(owner, spender, ERC20Extended.allowance(owner, spender) - amount); + emit IERC20.Approval( + owner, + spender, + ERC20Extended.allowance(owner, spender) - amount + ); vm.expectEmit(true, true, false, true); emit IERC20.Transfer(owner, zeroAddress, amount); @@ -461,7 +513,10 @@ contract ERC20Test is Test { emit IERC20.Transfer(zeroAddress, owner, amount); ERC20Extended.mint(owner, amount); assertEq(ERC20Extended.balanceOf(owner), amount); - assertEq(ERC20Extended.totalSupply(), (amount + _INITIAL_SUPPLY * multiplier)); + assertEq( + ERC20Extended.totalSupply(), + (amount + _INITIAL_SUPPLY * multiplier) + ); vm.stopPrank(); } @@ -529,7 +584,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -554,7 +618,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -579,7 +652,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -609,7 +691,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -631,7 +722,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -653,7 +753,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -698,7 +807,13 @@ contract ERC20Test is Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(ERC20Extended.DOMAIN_SEPARATOR(), digest); } @@ -767,8 +882,17 @@ contract ERC20Test is Test { assertEq(ERC20Extended.balanceOf(to), amount); } - function testFuzzTransferInvalidAmount(address owner, address to, uint256 amount) public { - vm.assume(owner != deployer && owner != zeroAddress && to != zeroAddress && amount != 0); + function testFuzzTransferInvalidAmount( + address owner, + address to, + uint256 amount + ) public { + vm.assume( + owner != deployer && + owner != zeroAddress && + to != zeroAddress && + amount != 0 + ); vm.prank(owner); vm.expectRevert(bytes("ERC20: transfer amount exceeds balance")); ERC20Extended.transfer(to, amount); @@ -784,9 +908,19 @@ contract ERC20Test is Test { assertEq(ERC20Extended.allowance(owner, spender), amount); } - function testFuzzTransferFromSuccess(address owner, address to, uint256 amount) public { + function testFuzzTransferFromSuccess( + address owner, + address to, + uint256 amount + ) public { address spender = self; - vm.assume(to != zeroAddress && owner != zeroAddress && owner != to && to != spender && to != deployer); + vm.assume( + to != zeroAddress && + owner != zeroAddress && + owner != to && + to != spender && + to != deployer + ); amount = bound(amount, 0, type(uint64).max); uint256 give = type(uint256).max; deal(ERC20ExtendedAddr, owner, give); @@ -805,9 +939,12 @@ contract ERC20Test is Test { assertEq(ERC20Extended.allowance(owner, spender), 0); } - function testFuzzTransferFromInsufficientAllowance(address owner, address to, uint256 amount, uint8 increment) - public - { + function testFuzzTransferFromInsufficientAllowance( + address owner, + address to, + uint256 amount, + uint8 increment + ) public { address spender = self; vm.assume(to != zeroAddress && owner != zeroAddress && increment != 0); amount = bound(amount, 0, type(uint64).max); @@ -862,7 +999,11 @@ contract ERC20Test is Test { assertEq(ERC20Extended.allowance(owner, spender), 0); } - function testFuzzBurnFromInsufficientAllowance(address owner, uint256 amount, uint8 increment) public { + function testFuzzBurnFromInsufficientAllowance( + address owner, + uint256 amount, + uint8 increment + ) public { vm.assume(owner != zeroAddress && owner != deployer && increment != 0); address spender = self; amount = bound(amount, 0, type(uint64).max); @@ -886,11 +1027,17 @@ contract ERC20Test is Test { emit IERC20.Transfer(zeroAddress, ownerAddr, amount); ERC20Extended.mint(ownerAddr, amount); assertEq(ERC20Extended.balanceOf(ownerAddr), amount); - assertEq(ERC20Extended.totalSupply(), (amount + _INITIAL_SUPPLY * multiplier)); + assertEq( + ERC20Extended.totalSupply(), + (amount + _INITIAL_SUPPLY * multiplier) + ); vm.stopPrank(); } - function testFuzzMintNonMinter(string calldata owner, uint256 amount) public { + function testFuzzMintNonMinter( + string calldata owner, + uint256 amount + ) public { vm.expectRevert(bytes("AccessControl: access is denied")); ERC20Extended.mint(makeAddr(owner), amount); } @@ -911,13 +1058,20 @@ contract ERC20Test is Test { vm.stopPrank(); } - function testFuzzSetMinterNonOwner(address msgSender, string calldata minter) public { + function testFuzzSetMinterNonOwner( + address msgSender, + string calldata minter + ) public { vm.assume(msgSender != deployer); vm.expectRevert(bytes("Ownable: caller is not the owner")); ERC20Extended.set_minter(makeAddr(minter), true); } - function testFuzzPermitSuccess(string calldata owner, string calldata spender, uint16 increment) public { + function testFuzzPermitSuccess( + string calldata owner, + string calldata spender, + uint16 increment + ) public { (address ownerAddr, uint256 key) = makeAddrAndKey(owner); address spenderAddr = makeAddr(spender); uint256 amount = block.number; @@ -931,7 +1085,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + ownerAddr, + spenderAddr, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -942,9 +1105,15 @@ contract ERC20Test is Test { assertEq(ERC20Extended.nonces(ownerAddr), 1); } - function testFuzzPermitInvalid(string calldata owner, string calldata spender, uint16 increment) public { - vm.assume(keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong"))); - (address ownerAddr,) = makeAddrAndKey(owner); + function testFuzzPermitInvalid( + string calldata owner, + string calldata spender, + uint16 increment + ) public { + vm.assume( + keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong")) + ); + (address ownerAddr, ) = makeAddrAndKey(owner); (, uint256 keyWrong) = makeAddrAndKey("ownerWrong"); address spenderAddr = makeAddr(spender); uint256 amount = block.number; @@ -958,7 +1127,16 @@ contract ERC20Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, ownerAddr, spenderAddr, amount, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + ownerAddr, + spenderAddr, + amount, + nonce, + deadline + ) + ) ) ) ); @@ -986,7 +1164,11 @@ contract ERC20Test is Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); + vm.assume( + randomHex != hex"0f" && + randomSalt != bytes32(0) && + randomExtensions.length != 0 + ); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -1003,17 +1185,32 @@ contract ERC20Test is Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, ERC20ExtendedAddr); assertTrue(salt != randomSalt); - assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); + assertTrue( + keccak256(abi.encode(extensions)) != + keccak256(abi.encode(randomExtensions)) + ); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(ERC20Extended.DOMAIN_SEPARATOR(), digest); } - function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { + function testFuzzTransferOwnershipSuccess( + address newOwner1, + address newOwner2 + ) public { vm.assume( - newOwner1 != zeroAddress && newOwner1 != deployer && newOwner1 != newOwner2 && newOwner2 != zeroAddress + newOwner1 != zeroAddress && + newOwner1 != deployer && + newOwner1 != newOwner2 && + newOwner2 != zeroAddress ); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -1044,7 +1241,10 @@ contract ERC20Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { + function testFuzzTransferOwnershipNonOwner( + address nonOwner, + address newOwner + ) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -1099,9 +1299,21 @@ contract ERC20Invariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - bytes memory args = abi.encode(_NAME, _SYMBOL, _INITIAL_SUPPLY, _NAME_EIP712, _VERSION_EIP712); - ERC20Extended = IERC20Extended(vyperDeployer.deployContract("src/tokens/", "ERC20", args)); - erc20Handler = new ERC20Handler(ERC20Extended, _INITIAL_SUPPLY, deployer); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + _INITIAL_SUPPLY, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC20Extended = IERC20Extended( + vyperDeployer.deployContract("src/tokens/", "ERC20", args) + ); + erc20Handler = new ERC20Handler( + ERC20Extended, + _INITIAL_SUPPLY, + deployer + ); targetContract(address(erc20Handler)); targetSender(deployer); } @@ -1137,13 +1349,23 @@ contract ERC20Handler { token.approve(spender, amount); } - function transferFrom(address ownerAddr, address to, uint256 amount) public { + function transferFrom( + address ownerAddr, + address to, + uint256 amount + ) public { token.transferFrom(ownerAddr, to, amount); } - function permit(address ownerAddr, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) - public - { + function permit( + address ownerAddr, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { token.permit(ownerAddr, spender, value, deadline, v, r, s); } diff --git a/test/tokens/ERC721.t.sol b/test/tokens/ERC721.t.sol index 755e482a..b1e69816 100644 --- a/test/tokens/ERC721.t.sol +++ b/test/tokens/ERC721.t.sol @@ -25,9 +25,17 @@ contract ERC721Test is Test { string private constant _NAME_EIP712 = "MyNFT"; string private constant _VERSION_EIP712 = "1"; bytes32 private constant _TYPE_HASH = - keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); + keccak256( + bytes( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ) + ); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256(bytes("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)")); + keccak256( + bytes( + "Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)" + ) + ); VyperDeployer private vyperDeployer = new VyperDeployer(); @@ -49,7 +57,11 @@ contract ERC721Test is Test { * @param tokenId The 32-byte identifier of the token. * @param receiver The 20-byte receiver address. */ - function _transferSuccess(address owner, uint256 tokenId, address receiver) internal { + function _transferSuccess( + address owner, + uint256 tokenId, + address receiver + ) internal { assertEq(ERC721Extended.ownerOf(tokenId), receiver); assertEq(ERC721Extended.getApproved(tokenId), zeroAddress); assertEq(ERC721Extended.balanceOf(owner), 1); @@ -83,11 +95,24 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: caller is not token owner or approved")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId, + data + ) ); } vm.stopPrank(); @@ -96,11 +121,24 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: transfer from incorrect owner")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + receiver, + receiver, + tokenId + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + receiver, + receiver, + tokenId, + data + ) ); } vm.stopPrank(); @@ -109,11 +147,24 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: invalid token ID")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId + 2) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + receiver, + receiver, + tokenId + 2 + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, receiver, receiver, tokenId + 2, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + receiver, + receiver, + tokenId + 2, + data + ) ); } vm.stopPrank(); @@ -122,11 +173,24 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721: transfer to the zero address")); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, zeroAddress, tokenId) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + zeroAddress, + tokenId + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, zeroAddress, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + zeroAddress, + tokenId, + data + ) ); } vm.stopPrank(); @@ -163,11 +227,24 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId, + data + ) ); } _transferSuccess(owner, tokenId, receiver); @@ -180,11 +257,24 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId, + data + ) ); } _transferSuccess(owner, tokenId, receiver); @@ -197,11 +287,24 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId, + data + ) ); } _transferSuccess(owner, tokenId, receiver); @@ -217,11 +320,24 @@ contract ERC721Test is Test { emit IERC721.Transfer(owner, receiver, tokenId); if (!withData) { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId + ) ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId, + data + ) ); } _transferSuccess(owner, tokenId, receiver); @@ -233,10 +349,20 @@ contract ERC721Test is Test { vm.expectEmit(true, true, true, false); emit IERC721.Transfer(owner, owner, tokenId); if (!withData) { - Address.functionCall(ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, owner, tokenId)); + Address.functionCall( + ERC721ExtendedAddr, + abi.encodeWithSignature(transferFunction, owner, owner, tokenId) + ); } else { Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, owner, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + owner, + tokenId, + data + ) ); } assertEq(ERC721Extended.ownerOf(tokenId), owner); @@ -250,7 +376,14 @@ contract ERC721Test is Test { /** * @dev Validates all possible reverts. */ - _transferReverts(transferFunction, owner, tokenId, receiver, withData, data); + _transferReverts( + transferFunction, + owner, + tokenId, + receiver, + withData, + data + ); } /** @@ -277,12 +410,28 @@ contract ERC721Test is Test { ) internal { uint256 snapshot = vm.snapshot(); _shouldTransferTokensByUsers( - transferFunction, owner, approved, operator, tokenId, makeAddr("receiver"), true, data + transferFunction, + owner, + approved, + operator, + tokenId, + makeAddr("receiver"), + true, + data ); vm.revertTo(snapshot); snapshot = vm.snapshot(); - _shouldTransferTokensByUsers(transferFunction, owner, approved, operator, tokenId, receiver, true, data); + _shouldTransferTokensByUsers( + transferFunction, + owner, + approved, + operator, + tokenId, + receiver, + true, + data + ); vm.revertTo(snapshot); snapshot = vm.snapshot(); @@ -290,7 +439,14 @@ contract ERC721Test is Test { vm.expectEmit(true, true, true, true, receiver); emit ERC721ReceiverMock.Received(owner, owner, tokenId, data); Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId, + data + ) ); _transferSuccess(owner, tokenId, receiver); vm.stopPrank(); @@ -301,7 +457,14 @@ contract ERC721Test is Test { vm.expectEmit(true, true, true, true, receiver); emit ERC721ReceiverMock.Received(approved, owner, tokenId, data); Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId, + data + ) ); _transferSuccess(owner, tokenId, receiver); vm.stopPrank(); @@ -310,14 +473,29 @@ contract ERC721Test is Test { vm.startPrank(owner); vm.expectRevert(bytes("ERC721: invalid token ID")); Address.functionCall( - ERC721ExtendedAddr, abi.encodeWithSignature(transferFunction, owner, receiver, tokenId + 2, data) + ERC721ExtendedAddr, + abi.encodeWithSignature( + transferFunction, + owner, + receiver, + tokenId + 2, + data + ) ); vm.stopPrank(); } function setUp() public { - bytes memory args = abi.encode(_NAME, _SYMBOL, _BASE_URI, _NAME_EIP712, _VERSION_EIP712); - ERC721Extended = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + _BASE_URI, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC721Extended = IERC721Extended( + vyperDeployer.deployContract("src/tokens/", "ERC721", args) + ); ERC721ExtendedAddr = address(ERC721Extended); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( @@ -341,8 +519,16 @@ contract ERC721Test is Test { emit IERC721Extended.OwnershipTransferred(zeroAddress, deployer); vm.expectEmit(true, false, false, true); emit IERC721Extended.RoleMinterChanged(deployer, true); - bytes memory args = abi.encode(_NAME, _SYMBOL, _BASE_URI, _NAME_EIP712, _VERSION_EIP712); - ERC721ExtendedInitialEvent = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + _BASE_URI, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC721ExtendedInitialEvent = IERC721Extended( + vyperDeployer.deployContract("src/tokens/", "ERC721", args) + ); assertEq(ERC721ExtendedInitialEvent.name(), _NAME); assertEq(ERC721ExtendedInitialEvent.symbol(), _SYMBOL); assertEq(ERC721ExtendedInitialEvent.totalSupply(), 0); @@ -353,9 +539,17 @@ contract ERC721Test is Test { function testSupportsInterfaceSuccess() public { assertTrue(ERC721Extended.supportsInterface(type(IERC165).interfaceId)); assertTrue(ERC721Extended.supportsInterface(type(IERC721).interfaceId)); - assertTrue(ERC721Extended.supportsInterface(type(IERC721Metadata).interfaceId)); - assertTrue(ERC721Extended.supportsInterface(type(IERC721Enumerable).interfaceId)); - assertTrue(ERC721Extended.supportsInterface(type(IERC4494).interfaceId)); + assertTrue( + ERC721Extended.supportsInterface(type(IERC721Metadata).interfaceId) + ); + assertTrue( + ERC721Extended.supportsInterface( + type(IERC721Enumerable).interfaceId + ) + ); + assertTrue( + ERC721Extended.supportsInterface(type(IERC4494).interfaceId) + ); assertTrue(ERC721Extended.supportsInterface(0x49064906)); } @@ -363,7 +557,10 @@ contract ERC721Test is Test { uint256 startGas = gasleft(); ERC721Extended.supportsInterface(type(IERC165).interfaceId); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && ERC721Extended.supportsInterface(type(IERC165).interfaceId)); + assertTrue( + gasUsed <= 30_000 && + ERC721Extended.supportsInterface(type(IERC165).interfaceId) + ); } function testSupportsInterfaceInvalidInterfaceId() public { @@ -374,7 +571,9 @@ contract ERC721Test is Test { uint256 startGas = gasleft(); ERC721Extended.supportsInterface(0x0011bbff); uint256 gasUsed = startGas - gasleft(); - assertTrue(gasUsed <= 30_000 && !ERC721Extended.supportsInterface(0x0011bbff)); + assertTrue( + gasUsed <= 30_000 && !ERC721Extended.supportsInterface(0x0011bbff) + ); } function testBalanceOfCase1() public { @@ -446,8 +645,10 @@ contract ERC721Test is Test { string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.None + ); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri1); @@ -471,7 +672,13 @@ contract ERC721Test is Test { ); _shouldTransferSafely( - "safeTransferFrom(address,address,uint256,bytes)", owner, approved, operator, 0, receiver, new bytes(0) + "safeTransferFrom(address,address,uint256,bytes)", + owner, + approved, + operator, + 0, + receiver, + new bytes(0) ); } @@ -482,8 +689,10 @@ contract ERC721Test is Test { string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.None + ); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri1); @@ -496,21 +705,32 @@ contract ERC721Test is Test { vm.stopPrank(); _shouldTransferSafely( - "safeTransferFrom(address,address,uint256,bytes)", owner, approved, operator, 0, receiver, new bytes(42) + "safeTransferFrom(address,address,uint256,bytes)", + owner, + approved, + operator, + 0, + receiver, + new bytes(42) ); } function testSafeTransferFromReceiverInvalidReturnIdentifier() public { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock(0x00bb8833, ERC721ReceiverMock.Error.None); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + 0x00bb8833, + ERC721ReceiverMock.Error.None + ); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); vm.stopPrank(); vm.startPrank(owner); - vm.expectRevert(bytes("ERC721: transfer to non-ERC721Receiver implementer")); + vm.expectRevert( + bytes("ERC721: transfer to non-ERC721Receiver implementer") + ); ERC721Extended.safeTransferFrom(owner, receiver, 0, new bytes(0)); vm.stopPrank(); } @@ -519,8 +739,10 @@ contract ERC721Test is Test { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithMessage); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.RevertWithMessage + ); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); @@ -536,8 +758,10 @@ contract ERC721Test is Test { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithoutMessage); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.RevertWithoutMessage + ); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); @@ -553,8 +777,10 @@ contract ERC721Test is Test { address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.Panic); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.Panic + ); address receiver = address(erc721ReceiverMock); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, uri); @@ -727,7 +953,11 @@ contract ERC721Test is Test { vm.stopPrank(); vm.startPrank(makeAddr("nonOwner")); - vm.expectRevert(bytes("ERC721: approve caller is not token owner or approved for all")); + vm.expectRevert( + bytes( + "ERC721: approve caller is not token owner or approved for all" + ) + ); ERC721Extended.approve(makeAddr("to"), tokenId); vm.stopPrank(); } @@ -746,7 +976,11 @@ contract ERC721Test is Test { vm.stopPrank(); vm.startPrank(spender); - vm.expectRevert(bytes("ERC721: approve caller is not token owner or approved for all")); + vm.expectRevert( + bytes( + "ERC721: approve caller is not token owner or approved for all" + ) + ); ERC721Extended.approve(makeAddr("to"), tokenId); vm.stopPrank(); } @@ -912,8 +1146,16 @@ contract ERC721Test is Test { } function testTokenURINoBaseURI() public { - bytes memory args = abi.encode(_NAME, _SYMBOL, "", _NAME_EIP712, _VERSION_EIP712); - ERC721ExtendedNoBaseURI = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + "", + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC721ExtendedNoBaseURI = IERC721Extended( + vyperDeployer.deployContract("src/tokens/", "ERC721", args) + ); address owner = makeAddr("owner"); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1018,23 +1260,44 @@ contract ERC721Test is Test { ERC721Extended.burn(0); vm.stopPrank(); assertEq(ERC721Extended.totalSupply(), 2); - assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), tokenId + 2); - assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), tokenId + 1); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), + tokenId + 2 + ); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), + tokenId + 1 + ); vm.startPrank(owner); ERC721Extended.safeTransferFrom(owner, other, tokenId + 1, ""); vm.stopPrank(); assertEq(ERC721Extended.totalSupply(), 2); - assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), tokenId + 2); - assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId), tokenId + 1); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), + tokenId + 2 + ); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(other, tokenId), + tokenId + 1 + ); vm.startPrank(deployer); ERC721Extended.safe_mint(owner, ""); vm.stopPrank(); assertEq(ERC721Extended.totalSupply(), 3); - assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), tokenId + 2); - assertEq(ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), tokenId + 3); - assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId), tokenId + 1); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(owner, tokenId), + tokenId + 2 + ); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(owner, tokenId + 1), + tokenId + 3 + ); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(other, tokenId), + tokenId + 1 + ); } function testTokenOfOwnerByIndexReverts() public { @@ -1062,8 +1325,14 @@ contract ERC721Test is Test { vm.expectRevert(bytes("ERC721Enumerable: owner index out of bounds")); ERC721Extended.tokenOfOwnerByIndex(owner, tokenId); assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId), tokenId); - assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 1), tokenId + 1); - assertEq(ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 2), tokenId + 2); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 1), + tokenId + 1 + ); + assertEq( + ERC721Extended.tokenOfOwnerByIndex(other, tokenId + 2), + tokenId + 2 + ); } function testBurnSuccess() public { @@ -1199,7 +1468,11 @@ contract ERC721Test is Test { * @dev To display the default storage layout for a contract * in Vyper, use `vyper -f layout yourFileName.vy`. */ - vm.store(ERC721ExtendedAddr, bytes32(uint256(18_446_744_073_709_551_627)), bytes32(0)); + vm.store( + ERC721ExtendedAddr, + bytes32(uint256(18_446_744_073_709_551_627)), + bytes32(0) + ); vm.expectRevert(bytes("ERC721: token already minted")); ERC721Extended.safe_mint(owner, ""); vm.stopPrank(); @@ -1207,8 +1480,10 @@ contract ERC721Test is Test { function testSafeMintReceiverContract() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.None + ); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -1221,19 +1496,26 @@ contract ERC721Test is Test { } function testSafeMintReceiverContractInvalidReturnIdentifier() public { - ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock(0x00bb8833, ERC721ReceiverMock.Error.None); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + 0x00bb8833, + ERC721ReceiverMock.Error.None + ); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); - vm.expectRevert(bytes("ERC721: transfer to non-ERC721Receiver implementer")); + vm.expectRevert( + bytes("ERC721: transfer to non-ERC721Receiver implementer") + ); ERC721Extended.safe_mint(owner, uri); vm.stopPrank(); } function testSafeMintReceiverContractRevertsWithMessage() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithMessage); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.RevertWithMessage + ); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1244,8 +1526,10 @@ contract ERC721Test is Test { function testSafeMintReceiverContractRevertsWithoutMessage() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.RevertWithoutMessage); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.RevertWithoutMessage + ); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1256,8 +1540,10 @@ contract ERC721Test is Test { function testSafeMintReceiverContractRevertsWithPanic() public { bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.Panic); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.Panic + ); address owner = address(erc721ReceiverMock); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1290,7 +1576,11 @@ contract ERC721Test is Test { * @dev To display the default storage layout for a contract * in Vyper, use `vyper -f layout yourFileName.vy`. */ - vm.store(ERC721ExtendedAddr, bytes32(uint256(18_446_744_073_709_551_627)), bytes32(type(uint256).max)); + vm.store( + ERC721ExtendedAddr, + bytes32(uint256(18_446_744_073_709_551_627)), + bytes32(type(uint256).max) + ); vm.prank(deployer); vm.expectRevert(); ERC721Extended.safe_mint(makeAddr("owner"), "my_awesome_nft_uri"); @@ -1348,7 +1638,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spender, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1378,7 +1676,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spender, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1408,7 +1714,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spender, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1443,7 +1757,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spender, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1470,7 +1792,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spender, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1497,7 +1827,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spender, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spender, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1542,7 +1880,13 @@ contract ERC721Test is Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(ERC721Extended.DOMAIN_SEPARATOR(), digest); } @@ -1598,11 +1942,22 @@ contract ERC721Test is Test { ERC721Extended.renounce_ownership(); } - function testFuzzTransferFrom(address owner, address approved, address operator) public { - vm.assume(owner > address(4_096) && approved > address(4_096) && operator > address(4_096)); + function testFuzzTransferFrom( + address owner, + address approved, + address operator + ) public { vm.assume( - owner != approved && owner != operator && owner != zeroAddress && owner.code.length == 0 - && owner != makeAddr("receiver") + owner > address(4_096) && + approved > address(4_096) && + operator > address(4_096) + ); + vm.assume( + owner != approved && + owner != operator && + owner != zeroAddress && + owner.code.length == 0 && + owner != makeAddr("receiver") ); string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; @@ -1628,19 +1983,31 @@ contract ERC721Test is Test { ); } - function testFuzzSafeTransferFromWithData(address owner, address approved, address operator, bytes memory data) - public - { - vm.assume(owner > address(4_096) && approved > address(4_096) && operator > address(4_096)); + function testFuzzSafeTransferFromWithData( + address owner, + address approved, + address operator, + bytes memory data + ) public { vm.assume( - owner != approved && owner != operator && owner != zeroAddress && owner.code.length == 0 - && owner != makeAddr("receiver") + owner > address(4_096) && + approved > address(4_096) && + operator > address(4_096) + ); + vm.assume( + owner != approved && + owner != operator && + owner != zeroAddress && + owner.code.length == 0 && + owner != makeAddr("receiver") ); string memory uri1 = "my_awesome_nft_uri_1"; string memory uri2 = "my_awesome_nft_uri_2"; bytes4 receiverMagicValue = type(IERC721Receiver).interfaceId; - ERC721ReceiverMock erc721ReceiverMock = - new ERC721ReceiverMock(receiverMagicValue, ERC721ReceiverMock.Error.None); + ERC721ReceiverMock erc721ReceiverMock = new ERC721ReceiverMock( + receiverMagicValue, + ERC721ReceiverMock.Error.None + ); address receiver = address(erc721ReceiverMock); vm.assume(owner != receiver); vm.startPrank(deployer); @@ -1665,12 +2032,23 @@ contract ERC721Test is Test { ); _shouldTransferSafely( - "safeTransferFrom(address,address,uint256,bytes)", owner, approved, operator, 0, receiver, data + "safeTransferFrom(address,address,uint256,bytes)", + owner, + approved, + operator, + 0, + receiver, + data ); } - function testFuzzApproveClearingApprovalWithNoPriorApproval(address owner, address spender) public { - vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); + function testFuzzApproveClearingApprovalWithNoPriorApproval( + address owner, + address spender + ) public { + vm.assume( + owner != spender && owner != zeroAddress && owner.code.length == 0 + ); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -1686,8 +2064,13 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzApproveClearingApprovalWithPriorApproval(address owner, address spender1) public { - vm.assume(owner != spender1 && owner != zeroAddress && owner.code.length == 0); + function testFuzzApproveClearingApprovalWithPriorApproval( + address owner, + address spender1 + ) public { + vm.assume( + owner != spender1 && owner != zeroAddress && owner.code.length == 0 + ); vm.assume(spender1 > address(4_096)); address spender2 = zeroAddress; string memory uri = "my_awesome_nft_uri"; @@ -1709,8 +2092,13 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzApproveWithNoPriorApproval(address owner, address spender) public { - vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); + function testFuzzApproveWithNoPriorApproval( + address owner, + address spender + ) public { + vm.assume( + owner != spender && owner != zeroAddress && owner.code.length == 0 + ); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -1726,8 +2114,13 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzApproveWithPriorApproval(address owner, address spender) public { - vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); + function testFuzzApproveWithPriorApproval( + address owner, + address spender + ) public { + vm.assume( + owner != spender && owner != zeroAddress && owner.code.length == 0 + ); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; @@ -1759,14 +2152,31 @@ contract ERC721Test is Test { vm.stopPrank(); vm.startPrank(nonOwner); - vm.expectRevert(bytes("ERC721: approve caller is not token owner or approved for all")); + vm.expectRevert( + bytes( + "ERC721: approve caller is not token owner or approved for all" + ) + ); ERC721Extended.approve(makeAddr("to"), tokenId); vm.stopPrank(); } - function testFuzzApproveFromOperatorAddress(address owner, address operator, address spender) public { - vm.assume(owner > address(4_096) && operator > address(4_096) && spender > address(4_096)); - vm.assume(owner != operator && owner != spender && owner != zeroAddress && owner.code.length == 0); + function testFuzzApproveFromOperatorAddress( + address owner, + address operator, + address spender + ) public { + vm.assume( + owner > address(4_096) && + operator > address(4_096) && + spender > address(4_096) + ); + vm.assume( + owner != operator && + owner != spender && + owner != zeroAddress && + owner.code.length == 0 + ); string memory uri = "my_awesome_nft_uri"; uint256 tokenId = 0; vm.startPrank(deployer); @@ -1785,9 +2195,14 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzSetApprovalForAllSuccess(address owner, address operator) public { + function testFuzzSetApprovalForAllSuccess( + address owner, + address operator + ) public { vm.assume(owner > address(4_096) && operator > address(4_096)); - vm.assume(owner != operator && owner != zeroAddress && owner.code.length == 0); + vm.assume( + owner != operator && owner != zeroAddress && owner.code.length == 0 + ); bool approved = true; string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1812,8 +2227,13 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzGetApprovedApprovedTokenId(address owner, address spender) public { - vm.assume(owner != spender && owner != zeroAddress && owner.code.length == 0); + function testFuzzGetApprovedApprovedTokenId( + address owner, + address spender + ) public { + vm.assume( + owner != spender && owner != zeroAddress && owner.code.length == 0 + ); vm.assume(spender > address(4_096)); string memory uri = "my_awesome_nft_uri"; vm.startPrank(deployer); @@ -1910,13 +2330,20 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzSetMinterNonOwner(address msgSender, string calldata minter) public { + function testFuzzSetMinterNonOwner( + address msgSender, + string calldata minter + ) public { vm.assume(msgSender != deployer); vm.expectRevert(bytes("Ownable: caller is not the owner")); ERC721Extended.set_minter(makeAddr(minter), true); } - function testFuzzPermitSuccess(string calldata owner, string calldata spender, uint16 increment) public { + function testFuzzPermitSuccess( + string calldata owner, + string calldata spender, + uint16 increment + ) public { (address ownerAddr, uint256 key) = makeAddrAndKey(owner); address spenderAddr = makeAddr(spender); uint256 tokenId = 0; @@ -1935,7 +2362,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spenderAddr, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spenderAddr, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1946,9 +2381,15 @@ contract ERC721Test is Test { assertEq(ERC721Extended.nonces(tokenId), 1); } - function testFuzzPermitInvalid(string calldata owner, string calldata spender, uint16 increment) public { - vm.assume(keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong"))); - (address ownerAddr,) = makeAddrAndKey(owner); + function testFuzzPermitInvalid( + string calldata owner, + string calldata spender, + uint16 increment + ) public { + vm.assume( + keccak256(abi.encode(owner)) != keccak256(abi.encode("ownerWrong")) + ); + (address ownerAddr, ) = makeAddrAndKey(owner); (, uint256 keyWrong) = makeAddrAndKey("ownerWrong"); address spenderAddr = makeAddr(spender); uint256 tokenId = 0; @@ -1967,7 +2408,15 @@ contract ERC721Test is Test { abi.encodePacked( "\x19\x01", domainSeparator, - keccak256(abi.encode(_PERMIT_TYPE_HASH, spenderAddr, tokenId, nonce, deadline)) + keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + spenderAddr, + tokenId, + nonce, + deadline + ) + ) ) ) ); @@ -1995,7 +2444,11 @@ contract ERC721Test is Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); + vm.assume( + randomHex != hex"0f" && + randomSalt != bytes32(0) && + randomExtensions.length != 0 + ); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -2012,17 +2465,32 @@ contract ERC721Test is Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, ERC721ExtendedAddr); assertTrue(salt != randomSalt); - assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); + assertTrue( + keccak256(abi.encode(extensions)) != + keccak256(abi.encode(randomExtensions)) + ); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(ERC721Extended.DOMAIN_SEPARATOR(), digest); } - function testFuzzTransferOwnershipSuccess(address newOwner1, address newOwner2) public { + function testFuzzTransferOwnershipSuccess( + address newOwner1, + address newOwner2 + ) public { vm.assume( - newOwner1 != zeroAddress && newOwner1 != deployer && newOwner1 != newOwner2 && newOwner2 != zeroAddress + newOwner1 != zeroAddress && + newOwner1 != deployer && + newOwner1 != newOwner2 && + newOwner2 != zeroAddress ); address oldOwner = deployer; vm.startPrank(oldOwner); @@ -2053,7 +2521,10 @@ contract ERC721Test is Test { vm.stopPrank(); } - function testFuzzTransferOwnershipNonOwner(address nonOwner, address newOwner) public { + function testFuzzTransferOwnershipNonOwner( + address nonOwner, + address newOwner + ) public { vm.assume(nonOwner != deployer); vm.prank(nonOwner); vm.expectRevert(bytes("Ownable: caller is not the owner")); @@ -2108,8 +2579,16 @@ contract ERC721Invariants is Test { address private deployer = address(vyperDeployer); function setUp() public { - bytes memory args = abi.encode(_NAME, _SYMBOL, _BASE_URI, _NAME_EIP712, _VERSION_EIP712); - ERC721Extended = IERC721Extended(vyperDeployer.deployContract("src/tokens/", "ERC721", args)); + bytes memory args = abi.encode( + _NAME, + _SYMBOL, + _BASE_URI, + _NAME_EIP712, + _VERSION_EIP712 + ); + ERC721Extended = IERC721Extended( + vyperDeployer.deployContract("src/tokens/", "ERC721", args) + ); erc721Handler = new ERC721Handler(ERC721Extended, deployer); targetContract(address(erc721Handler)); targetSender(deployer); @@ -2138,7 +2617,11 @@ contract ERC721Handler { owner = owner_; } - function safeTransferFrom(address ownerAddr, address to, bytes calldata data) public { + function safeTransferFrom( + address ownerAddr, + address to, + bytes calldata data + ) public { token.safeTransferFrom(ownerAddr, to, counter, data); } @@ -2158,7 +2641,13 @@ contract ERC721Handler { token.setApprovalForAll(operator, approved); } - function permit(address spender, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { + function permit( + address spender, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { token.permit(spender, counter, deadline, v, r, s); } diff --git a/test/tokens/interfaces/IERC1155Extended.sol b/test/tokens/interfaces/IERC1155Extended.sol index e6539bf2..bf87c467 100644 --- a/test/tokens/interfaces/IERC1155Extended.sol +++ b/test/tokens/interfaces/IERC1155Extended.sol @@ -4,7 +4,10 @@ pragma solidity ^0.8.23; import {IERC1155MetadataURI} from "openzeppelin/token/ERC1155/extensions/IERC1155MetadataURI.sol"; interface IERC1155Extended is IERC1155MetadataURI { - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); event RoleMinterChanged(address indexed minter, bool status); @@ -16,14 +19,27 @@ interface IERC1155Extended is IERC1155MetadataURI { function burn(address owner, uint256 id, uint256 amount) external; - function burn_batch(address owner, uint256[] calldata ids, uint256[] calldata amounts) external; + function burn_batch( + address owner, + uint256[] calldata ids, + uint256[] calldata amounts + ) external; function is_minter(address account) external view returns (bool); - function safe_mint(address owner, uint256 id, uint256 amount, bytes calldata data) external; - - function safe_mint_batch(address owner, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) - external; + function safe_mint( + address owner, + uint256 id, + uint256 amount, + bytes calldata data + ) external; + + function safe_mint_batch( + address owner, + uint256[] calldata ids, + uint256[] calldata amounts, + bytes calldata data + ) external; function set_minter(address minter, bool status) external; diff --git a/test/tokens/interfaces/IERC20Extended.sol b/test/tokens/interfaces/IERC20Extended.sol index c47f5194..f678cdb1 100644 --- a/test/tokens/interfaces/IERC20Extended.sol +++ b/test/tokens/interfaces/IERC20Extended.sol @@ -6,7 +6,10 @@ import {IERC20Permit} from "openzeppelin/token/ERC20/extensions/IERC20Permit.sol import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; interface IERC20Extended is IERC20Metadata, IERC20Permit, IERC5267 { - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); event RoleMinterChanged(address indexed minter, bool status); diff --git a/test/tokens/interfaces/IERC4494.sol b/test/tokens/interfaces/IERC4494.sol index 5aaac6f1..2d99b238 100644 --- a/test/tokens/interfaces/IERC4494.sol +++ b/test/tokens/interfaces/IERC4494.sol @@ -4,7 +4,14 @@ pragma solidity ^0.8.23; import {IERC165} from "openzeppelin/utils/introspection/IERC165.sol"; interface IERC4494 is IERC165 { - function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; + function permit( + address spender, + uint256 tokenId, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; function nonces(uint256 tokenId) external view returns (uint256); diff --git a/test/tokens/interfaces/IERC721Extended.sol b/test/tokens/interfaces/IERC721Extended.sol index ce0c27dd..b3d737b0 100644 --- a/test/tokens/interfaces/IERC721Extended.sol +++ b/test/tokens/interfaces/IERC721Extended.sol @@ -7,8 +7,17 @@ import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; import {IERC4906} from "openzeppelin/interfaces/IERC4906.sol"; import {IERC4494} from "./IERC4494.sol"; -interface IERC721Extended is IERC721Metadata, IERC721Enumerable, IERC4494, IERC5267, IERC4906 { - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); +interface IERC721Extended is + IERC721Metadata, + IERC721Enumerable, + IERC4494, + IERC5267, + IERC4906 +{ + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); event RoleMinterChanged(address indexed minter, bool status); diff --git a/test/tokens/mocks/ERC1155ReceiverMock.sol b/test/tokens/mocks/ERC1155ReceiverMock.sol index 0be565f6..9185f95f 100644 --- a/test/tokens/mocks/ERC1155ReceiverMock.sol +++ b/test/tokens/mocks/ERC1155ReceiverMock.sol @@ -18,11 +18,28 @@ contract ERC1155ReceiverMock is ERC165, IERC1155Receiver { bytes4 private batRetval; bool private batReverts; - event Received(address indexed operator, address indexed from, uint256 id, uint256 amount, bytes data); + event Received( + address indexed operator, + address indexed from, + uint256 id, + uint256 amount, + bytes data + ); - event BatchReceived(address indexed operator, address indexed from, uint256[] ids, uint256[] amounts, bytes data); + event BatchReceived( + address indexed operator, + address indexed from, + uint256[] ids, + uint256[] amounts, + bytes data + ); - constructor(bytes4 recRetval_, bool recReverts_, bytes4 batRetval_, bool batReverts_) { + constructor( + bytes4 recRetval_, + bool recReverts_, + bytes4 batRetval_, + bool batReverts_ + ) { recRetval = recRetval_; recReverts = recReverts_; batRetval = batRetval_; @@ -42,10 +59,13 @@ contract ERC1155ReceiverMock is ERC165, IERC1155Receiver { * to this smart contract. * @return bytes4 The 4-byte return identifier. */ - function onERC1155Received(address operator, address from, uint256 id, uint256 amount, bytes memory data) - external - returns (bytes4) - { + function onERC1155Received( + address operator, + address from, + uint256 id, + uint256 amount, + bytes memory data + ) external returns (bytes4) { // solhint-disable-next-line reason-string, custom-errors require(!recReverts, "ERC1155ReceiverMock: reverting on receive"); emit Received(operator, from, id, amount, data); diff --git a/test/tokens/mocks/ERC721ReceiverMock.sol b/test/tokens/mocks/ERC721ReceiverMock.sol index ee63dd58..c0bcf7e2 100644 --- a/test/tokens/mocks/ERC721ReceiverMock.sol +++ b/test/tokens/mocks/ERC721ReceiverMock.sol @@ -41,11 +41,12 @@ contract ERC721ReceiverMock is IERC721Receiver { * to this smart contract. * @return bytes4 The 4-byte return identifier. */ - function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) - public - override - returns (bytes4) - { + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes memory data + ) public override returns (bytes4) { if (_ERROR == Error.RevertWithMessage) { // solhint-disable-next-line custom-errors revert("ERC721ReceiverMock: reverting"); diff --git a/test/utils/Base64.t.sol b/test/utils/Base64.t.sol index 14d125bc..6a35ebf4 100644 --- a/test/utils/Base64.t.sol +++ b/test/utils/Base64.t.sol @@ -137,8 +137,14 @@ contract Base64Test is PRBTest { * @dev We remove the one trailing zero byte that stems from * the padding to ensure byte-level equality. */ - assertEq(string(returnDataStd.slice(0, returnDataStd.length - 1)), text); - assertEq(string(returnDataUrl.slice(0, returnDataUrl.length - 1)), text); + assertEq( + string(returnDataStd.slice(0, returnDataStd.length - 1)), + text + ); + assertEq( + string(returnDataUrl.slice(0, returnDataUrl.length - 1)), + text + ); } function testDecodeWithDoublePadding() public { @@ -152,8 +158,14 @@ contract Base64Test is PRBTest { * @dev We remove the two trailing zero bytes that stem from * the padding to ensure byte-level equality. */ - assertEq(string(returnDataStd.slice(0, returnDataStd.length - 2)), text); - assertEq(string(returnDataUrl.slice(0, returnDataUrl.length - 2)), text); + assertEq( + string(returnDataStd.slice(0, returnDataStd.length - 2)), + text + ); + assertEq( + string(returnDataUrl.slice(0, returnDataUrl.length - 2)), + text + ); } function testDecodeSingleCharacter() public { @@ -200,8 +212,14 @@ contract Base64Test is PRBTest { * @dev We remove the two trailing zero bytes that stem from * the padding to ensure byte-level equality. */ - assertEq(string(returnDataStd.slice(0, returnDataStd.length - 2)), text); - assertEq(string(returnDataUrl.slice(0, returnDataUrl.length - 2)), text); + assertEq( + string(returnDataStd.slice(0, returnDataStd.length - 2)), + text + ); + assertEq( + string(returnDataUrl.slice(0, returnDataUrl.length - 2)), + text + ); } function testDecodeSafeUrl() public { @@ -210,7 +228,11 @@ contract Base64Test is PRBTest { vm.expectRevert(bytes("Base64: invalid string")); base64.decode(data, false); bytes[] memory outputUrl = base64.decode(data, true); - bytes memory returnDataUrl = bytes.concat(outputUrl[0], outputUrl[1], outputUrl[2]); + bytes memory returnDataUrl = bytes.concat( + outputUrl[0], + outputUrl[1], + outputUrl[2] + ); assertEq(string(returnDataUrl), text); } diff --git a/test/utils/BatchDistributor.t.sol b/test/utils/BatchDistributor.t.sol index e97f49b5..18c9b11b 100644 --- a/test/utils/BatchDistributor.t.sol +++ b/test/utils/BatchDistributor.t.sol @@ -19,15 +19,23 @@ contract BatchDistributorTest is Test { address private batchDistributorAddr; function setUp() public { - batchDistributor = IBatchDistributor(vyperDeployer.deployContract("src/utils/", "BatchDistributor")); + batchDistributor = IBatchDistributor( + vyperDeployer.deployContract("src/utils/", "BatchDistributor") + ); batchDistributorAddr = address(batchDistributor); } function testDistributeEtherOneAddressSuccess() public { address alice = makeAddr("alice"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](1); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](1); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 2 wei + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); batchDistributor.distribute_ether{value: 2 wei}(batch); assertEq(alice.balance, 2 wei); @@ -38,11 +46,23 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 2 wei + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 100 wei + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 2_000 wei + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); batchDistributor.distribute_ether{value: 2_102 wei}(batch); assertEq(alice.balance, 2 wei); @@ -58,30 +78,59 @@ contract BatchDistributorTest is Test { address msgSender = address(makeAddr("msgSender")); vm.deal(msgSender, 1 ether); uint256 balance = msgSender.balance; - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 2 wei + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 100 wei + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 2_000 wei + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); vm.prank(msgSender); batchDistributor.distribute_ether{value: 1 ether}(batch); assertEq(alice.balance, 2 wei); assertEq(bob.balance, 100 wei); assertEq(carol.balance, 2_000 wei); - assertEq(msgSender.balance, balance - alice.balance - bob.balance - carol.balance); + assertEq( + msgSender.balance, + balance - alice.balance - bob.balance - carol.balance + ); assertEq(batchDistributorAddr.balance, 0); } - function testDistributeEtherRevertWithNoFallbackFunctionForReceipt() public { + function testDistributeEtherRevertWithNoFallbackFunctionForReceipt() + public + { address alice = batchDistributorAddr; address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 2 wei + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 100 wei + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 2_000 wei + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); /** * @dev The `BatchDistributor` contract does not have a `fallback` function @@ -92,15 +141,29 @@ contract BatchDistributorTest is Test { assertEq(batchDistributorAddr.balance, 0); } - function testDistributeEtherRevertWithNoFallbackFunctionForMsgSender() public { + function testDistributeEtherRevertWithNoFallbackFunctionForMsgSender() + public + { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 2 wei + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 100 wei + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 2_000 wei + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); /** * @dev The `Test` contract does not have a `fallback` function and must @@ -115,11 +178,23 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 2 wei}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 100 wei}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 2_000 wei}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 2 wei + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 100 wei + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 2_000 wei + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); /** * @dev Sends too little funds, which triggers an insufficient funds error. @@ -139,9 +214,15 @@ contract BatchDistributorTest is Test { erc20Mock.approve(batchDistributorAddr, 30); address alice = makeAddr("alice"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](1); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 30}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](1); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 30 + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); batchDistributor.distribute_token(erc20Mock, batch); vm.stopPrank(); @@ -161,11 +242,23 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 30}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 20}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 50}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 30 + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 20 + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 50 + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); batchDistributor.distribute_token(erc20Mock, batch); vm.stopPrank(); @@ -187,14 +280,31 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 30}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 20}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 50}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 30 + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 20 + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 50 + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); vm.expectRevert( - abi.encodeWithSelector(IERC20Errors.ERC20InsufficientAllowance.selector, batchDistributorAddr, 99, 100) + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientAllowance.selector, + batchDistributorAddr, + 99, + 100 + ) ); batchDistributor.distribute_token(erc20Mock, batch); assertEq(erc20Mock.balanceOf(batchDistributorAddr), 0); @@ -213,21 +323,41 @@ contract BatchDistributorTest is Test { address alice = makeAddr("alice"); address bob = makeAddr("bob"); address carol = makeAddr("carol"); - IBatchDistributor.Transaction[] memory transaction = new IBatchDistributor.Transaction[](3); - transaction[0] = IBatchDistributor.Transaction({recipient: alice, amount: 50}); - transaction[1] = IBatchDistributor.Transaction({recipient: bob, amount: 20}); - transaction[2] = IBatchDistributor.Transaction({recipient: carol, amount: 50}); - IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({txns: transaction}); + IBatchDistributor.Transaction[] + memory transaction = new IBatchDistributor.Transaction[](3); + transaction[0] = IBatchDistributor.Transaction({ + recipient: alice, + amount: 50 + }); + transaction[1] = IBatchDistributor.Transaction({ + recipient: bob, + amount: 20 + }); + transaction[2] = IBatchDistributor.Transaction({ + recipient: carol, + amount: 50 + }); + IBatchDistributor.Batch memory batch = IBatchDistributor.Batch({ + txns: transaction + }); - vm.expectRevert(abi.encodeWithSelector(IERC20Errors.ERC20InsufficientBalance.selector, arg3, 100, 120)); + vm.expectRevert( + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientBalance.selector, + arg3, + 100, + 120 + ) + ); batchDistributor.distribute_token(erc20Mock, batch); assertEq(erc20Mock.balanceOf(batchDistributorAddr), 0); vm.stopPrank(); } - function testFuzzDistributeEtherMultipleAddressesSuccess(IBatchDistributor.Batch memory batch, uint256 value) - public - { + function testFuzzDistributeEtherMultipleAddressesSuccess( + IBatchDistributor.Batch memory batch, + uint256 value + ) public { value = bound(value, type(uint16).max, type(uint32).max); vm.assume(batch.txns.length <= 50); for (uint256 i; i < batch.txns.length; ++i) { @@ -253,27 +383,48 @@ contract BatchDistributorTest is Test { address initialAccount, uint256 initialAmount ) public { - vm.assume(initialAccount != zeroAddress && initialAccount != batchDistributorAddr); - initialAmount = bound(initialAmount, type(uint16).max, type(uint32).max); + vm.assume( + initialAccount != zeroAddress && + initialAccount != batchDistributorAddr + ); + initialAmount = bound( + initialAmount, + type(uint16).max, + type(uint32).max + ); vm.assume(batch.txns.length <= 50); for (uint256 i; i < batch.txns.length; ++i) { batch.txns[i].amount = bound(batch.txns[i].amount, 1, 100); - vm.assume(batch.txns[i].recipient != batchDistributorAddr && batch.txns[i].recipient != zeroAddress); + vm.assume( + batch.txns[i].recipient != batchDistributorAddr && + batch.txns[i].recipient != zeroAddress + ); } uint256 valueAccumulator; string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; - ERC20Mock erc20Mock = new ERC20Mock(arg1, arg2, initialAccount, initialAmount); + ERC20Mock erc20Mock = new ERC20Mock( + arg1, + arg2, + initialAccount, + initialAmount + ); vm.startPrank(initialAccount); erc20Mock.approve(batchDistributorAddr, initialAmount); batchDistributor.distribute_token(erc20Mock, batch); vm.stopPrank(); for (uint256 i; i < batch.txns.length; ++i) { valueAccumulator += batch.txns[i].amount; - assertGe(erc20Mock.balanceOf(batch.txns[i].recipient), batch.txns[i].amount); + assertGe( + erc20Mock.balanceOf(batch.txns[i].recipient), + batch.txns[i].amount + ); } - assertGe(erc20Mock.balanceOf(initialAccount), initialAmount - valueAccumulator); + assertGe( + erc20Mock.balanceOf(initialAccount), + initialAmount - valueAccumulator + ); assertEq(erc20Mock.balanceOf(batchDistributorAddr), 0); } } @@ -288,11 +439,21 @@ contract BatchDistributorInvariants is Test { address private batchDistributorAddr; function setUp() public { - batchDistributor = IBatchDistributor(vyperDeployer.deployContract("src/utils/", "BatchDistributor")); + batchDistributor = IBatchDistributor( + vyperDeployer.deployContract("src/utils/", "BatchDistributor") + ); batchDistributorAddr = address(batchDistributor); address msgSender = makeAddr("msgSender"); - erc20Mock = new ERC20Mock("MyToken", "MTKN", msgSender, type(uint256).max); - batchDistributorHandler = new BatchDistributorHandler(batchDistributor, erc20Mock); + erc20Mock = new ERC20Mock( + "MyToken", + "MTKN", + msgSender, + type(uint256).max + ); + batchDistributorHandler = new BatchDistributorHandler( + batchDistributor, + erc20Mock + ); targetContract(address(batchDistributorHandler)); targetSender(msgSender); } @@ -319,7 +480,9 @@ contract BatchDistributorHandler { token = token_; } - function distribute_ether(IBatchDistributor.Batch calldata batch) public payable { + function distribute_ether( + IBatchDistributor.Batch calldata batch + ) public payable { batchDistributor.distribute_ether(batch); } diff --git a/test/utils/Create2Address.t.sol b/test/utils/Create2Address.t.sol index e4b0ad6f..52ad90f0 100644 --- a/test/utils/Create2Address.t.sol +++ b/test/utils/Create2Address.t.sol @@ -18,7 +18,9 @@ contract Create2AddressTest is Test { address private create2AddressAddr; function setUp() public { - create2Address = ICreate2Address(vyperDeployer.deployContract("src/utils/", "Create2Address")); + create2Address = ICreate2Address( + vyperDeployer.deployContract("src/utils/", "Create2Address") + ); create2AddressAddr = address(create2Address); } @@ -29,12 +31,27 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); + bytes memory bytecode = abi.encodePacked( + vm.getCode("ERC20Mock.sol:ERC20Mock"), + args + ); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address(salt, bytecodeHash, address(this)); + address create2AddressComputed = create2Address.compute_address( + salt, + bytecodeHash, + address(this) + ); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); - assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( + arg1, + arg2, + arg3, + arg4 + ); + assertEq( + create2AddressComputed, + address(create2AddressComputedOnChain) + ); } function testComputeAddressSelf() public { @@ -44,16 +61,30 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); + bytes memory bytecode = abi.encodePacked( + vm.getCode("ERC20Mock.sol:ERC20Mock"), + args + ); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address_self(salt, bytecodeHash); - address create2AddressOZComputed = - create2Impl.computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); + address create2AddressComputed = create2Address.compute_address_self( + salt, + bytecodeHash + ); + address create2AddressOZComputed = create2Impl + .computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); vm.prank(create2AddressAddr); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( + arg1, + arg2, + arg3, + arg4 + ); assertEq(create2AddressComputed, create2AddressOZComputed); - assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); + assertEq( + create2AddressComputed, + address(create2AddressComputedOnChain) + ); } function testFuzzComputeAddress(bytes32 salt, address deployer) public { @@ -62,13 +93,28 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); + bytes memory bytecode = abi.encodePacked( + vm.getCode("ERC20Mock.sol:ERC20Mock"), + args + ); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address(salt, bytecodeHash, deployer); + address create2AddressComputed = create2Address.compute_address( + salt, + bytecodeHash, + deployer + ); vm.prank(deployer); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); - assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( + arg1, + arg2, + arg3, + arg4 + ); + assertEq( + create2AddressComputed, + address(create2AddressComputedOnChain) + ); } function testFuzzComputeAddressSelf(bytes32 salt) public { @@ -77,15 +123,29 @@ contract Create2AddressTest is Test { address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; bytes memory args = abi.encode(arg1, arg2, arg3, arg4); - bytes memory bytecode = abi.encodePacked(vm.getCode("ERC20Mock.sol:ERC20Mock"), args); + bytes memory bytecode = abi.encodePacked( + vm.getCode("ERC20Mock.sol:ERC20Mock"), + args + ); bytes32 bytecodeHash = keccak256(bytecode); - address create2AddressComputed = create2Address.compute_address_self(salt, bytecodeHash); - address create2AddressOZComputed = - create2Impl.computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); + address create2AddressComputed = create2Address.compute_address_self( + salt, + bytecodeHash + ); + address create2AddressOZComputed = create2Impl + .computeAddressWithDeployer(salt, bytecodeHash, create2AddressAddr); vm.prank(create2AddressAddr); - ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}(arg1, arg2, arg3, arg4); + ERC20Mock create2AddressComputedOnChain = new ERC20Mock{salt: salt}( + arg1, + arg2, + arg3, + arg4 + ); assertEq(create2AddressComputed, create2AddressOZComputed); - assertEq(create2AddressComputed, address(create2AddressComputedOnChain)); + assertEq( + create2AddressComputed, + address(create2AddressComputedOnChain) + ); } } diff --git a/test/utils/CreateAddress.t.sol b/test/utils/CreateAddress.t.sol index b4ecd769..c9116943 100644 --- a/test/utils/CreateAddress.t.sol +++ b/test/utils/CreateAddress.t.sol @@ -20,7 +20,9 @@ contract CreateAddressTest is Test { address private createAddressAddr; function setUp() public { - createAddress = ICreateAddress(vyperDeployer.deployContract("src/utils/", "CreateAddress")); + createAddress = ICreateAddress( + vyperDeployer.deployContract("src/utils/", "CreateAddress") + ); createAddressAddr = address(createAddress); } @@ -39,9 +41,15 @@ contract CreateAddressTest is Test { function testComputeAddressNonce0x00() public { address alice = makeAddr("alice"); uint64 nonce = 0x00; - address createAddressComputed = createAddress.compute_address_rlp(alice, nonce); - - address createAddressComputedOnChain = create.computeAddress(alice, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + alice, + nonce + ); + + address createAddressComputedOnChain = create.computeAddress( + alice, + nonce + ); assertEq(createAddressComputed, createAddressComputedOnChain); } @@ -52,9 +60,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = 0x7f; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -65,9 +81,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint8).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -78,9 +102,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint16).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -91,9 +123,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint24).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -104,9 +144,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint32).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -117,9 +165,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint40).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -130,9 +186,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint48).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -143,9 +207,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint56).max; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -156,9 +228,17 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = uint64(type(uint64).max) - 1; vm.setNonce(self, nonce); - address createAddressComputed = createAddress.compute_address_rlp(self, nonce); - - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + address createAddressComputed = createAddress.compute_address_rlp( + self, + nonce + ); + + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -169,11 +249,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = 0x7f; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -185,11 +275,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint8).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -201,11 +301,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint16).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -217,11 +327,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint24).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -233,11 +353,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint32).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -249,11 +379,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint40).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -265,11 +405,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint48).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -281,11 +431,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = type(uint56).max; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -297,150 +457,310 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; uint64 nonce = uint64(type(uint64).max) - 1; vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressRevertTooHighNonce(uint256 nonce, address deployer) public { - nonce = bound(nonce, uint256(type(uint64).max), uint256(type(uint256).max)); + function testFuzzComputeAddressRevertTooHighNonce( + uint256 nonce, + address deployer + ) public { + nonce = bound( + nonce, + uint256(type(uint64).max), + uint256(type(uint256).max) + ); vm.expectRevert(bytes("RLP: invalid nonce value")); createAddress.compute_address_rlp(deployer, nonce); } - function testFuzzComputeAddressSelfRevertTooHighNonce(uint256 nonce) public { - nonce = bound(nonce, uint256(type(uint64).max), uint256(type(uint256).max)); + function testFuzzComputeAddressSelfRevertTooHighNonce( + uint256 nonce + ) public { + nonce = bound( + nonce, + uint256(type(uint64).max), + uint256(type(uint256).max) + ); vm.expectRevert(bytes("RLP: invalid nonce value")); createAddress.compute_address_rlp_self(nonce); } - function testFuzzComputeAddressNonce0x7f(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonce0x7f( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; nonce = uint64(bound(uint256(nonce), vm.getNonce(deployer) + 1, 0x7f)); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint8(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint8( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; nonce = uint64(bound(nonce, 0x7f + 1, uint256(type(uint8).max))); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint16(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint16( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(nonce, uint64(type(uint8).max) + 1, uint64(type(uint16).max))); + nonce = uint64( + bound(nonce, uint64(type(uint8).max) + 1, uint64(type(uint16).max)) + ); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint24(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint24( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint16).max) + 1, uint256(type(uint24).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint16).max) + 1, + uint256(type(uint24).max) + ) + ); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint32(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint32( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint24).max) + 1, uint256(type(uint32).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint24).max) + 1, + uint256(type(uint32).max) + ) + ); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint40(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint40( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint32).max) + 1, uint256(type(uint40).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint32).max) + 1, + uint256(type(uint40).max) + ) + ); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint48(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint48( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint40).max) + 1, uint256(type(uint48).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint40).max) + 1, + uint256(type(uint48).max) + ) + ); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint56(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint56( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint48).max) + 1, uint256(type(uint56).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint48).max) + 1, + uint256(type(uint56).max) + ) + ); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } - function testFuzzComputeAddressNonceUint64(uint64 nonce, address deployer) public { + function testFuzzComputeAddressNonceUint64( + uint64 nonce, + address deployer + ) public { string memory arg1 = "MyToken"; string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint56).max) + 1, uint256(type(uint64).max) - 1)); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint56).max) + 1, + uint256(type(uint64).max) - 1 + ) + ); vm.setNonce(deployer, nonce); - address createAddressComputed = createAddress.compute_address_rlp(deployer, nonce); + address createAddressComputed = createAddress.compute_address_rlp( + deployer, + nonce + ); vm.prank(deployer); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -451,11 +771,21 @@ contract CreateAddressTest is Test { uint256 arg4 = 100; nonce = uint64(bound(nonce, vm.getNonce(createAddressAddr) + 1, 0x7f)); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -465,13 +795,25 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), 0x7f + 1, uint256(type(uint8).max))); + nonce = uint64( + bound(uint256(nonce), 0x7f + 1, uint256(type(uint8).max)) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -481,13 +823,29 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint8).max) + 1, uint256(type(uint16).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint8).max) + 1, + uint256(type(uint16).max) + ) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -497,13 +855,29 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint16).max) + 1, uint256(type(uint24).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint16).max) + 1, + uint256(type(uint24).max) + ) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -513,13 +887,29 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint24).max) + 1, uint256(type(uint32).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint24).max) + 1, + uint256(type(uint32).max) + ) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -529,13 +919,29 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint32).max) + 1, uint256(type(uint40).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint32).max) + 1, + uint256(type(uint40).max) + ) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -545,13 +951,29 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint40).max) + 1, uint256(type(uint48).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint40).max) + 1, + uint256(type(uint48).max) + ) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -561,13 +983,29 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint48).max) + 1, uint256(type(uint56).max))); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint48).max) + 1, + uint256(type(uint56).max) + ) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } @@ -577,13 +1015,29 @@ contract CreateAddressTest is Test { string memory arg2 = "MTKN"; address arg3 = makeAddr("initialAccount"); uint256 arg4 = 100; - nonce = uint64(bound(uint256(nonce), uint256(type(uint56).max) + 1, uint256(type(uint64).max) - 1)); + nonce = uint64( + bound( + uint256(nonce), + uint256(type(uint56).max) + 1, + uint256(type(uint64).max) - 1 + ) + ); vm.setNonce(createAddressAddr, nonce); - address createAddressComputed = createAddress.compute_address_rlp_self(nonce); - address createAddressLibComputed = create.computeAddress(createAddressAddr, nonce); + address createAddressComputed = createAddress.compute_address_rlp_self( + nonce + ); + address createAddressLibComputed = create.computeAddress( + createAddressAddr, + nonce + ); vm.prank(createAddressAddr); - ERC20Mock createAddressComputedOnChain = new ERC20Mock(arg1, arg2, arg3, arg4); + ERC20Mock createAddressComputedOnChain = new ERC20Mock( + arg1, + arg2, + arg3, + arg4 + ); assertEq(createAddressComputed, createAddressLibComputed); assertEq(createAddressComputed, address(createAddressComputedOnChain)); } diff --git a/test/utils/ECDSA.t.sol b/test/utils/ECDSA.t.sol index 3febc6fc..b224dc6b 100644 --- a/test/utils/ECDSA.t.sol +++ b/test/utils/ECDSA.t.sol @@ -39,7 +39,9 @@ contract ECDSATest is Test { * @param signature The secp256k1 64/65-bytes signature. * @return short The 64-bytes EIP-2098 compliant signature. */ - function to2098Format(bytes memory signature) internal view returns (bytes memory) { + function to2098Format( + bytes memory signature + ) internal view returns (bytes memory) { if (signature.length != 65) revert InvalidSignatureLength(self); if (uint8(signature[32]) >> 7 == 1) revert InvalidSignatureSValue(self); bytes memory short = signature.slice(0, 64); @@ -81,7 +83,9 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); + vm.expectRevert( + abi.encodeWithSelector(InvalidSignatureLength.selector, self) + ); to2098Format(signature); } @@ -99,7 +103,9 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); + vm.expectRevert( + abi.encodeWithSelector(InvalidSignatureLength.selector, self) + ); to2098Format(signature); } @@ -161,7 +167,10 @@ contract ECDSATest is Test { bytes memory signatureWithoutVersion = abi.encodePacked(r, s); bytes1 version = 0x00; vm.expectRevert(bytes("ECDSA: invalid signature")); - ECDSA.recover_sig(hash, abi.encodePacked(signatureWithoutVersion, version)); + ECDSA.recover_sig( + hash, + abi.encodePacked(signatureWithoutVersion, version) + ); } function testRecoverWithWrongVersion() public { @@ -174,7 +183,10 @@ contract ECDSATest is Test { bytes memory signatureWithoutVersion = abi.encodePacked(r, s); bytes1 version = 0x02; vm.expectRevert(bytes("ECDSA: invalid signature")); - ECDSA.recover_sig(hash, abi.encodePacked(signatureWithoutVersion, version)); + ECDSA.recover_sig( + hash, + abi.encodePacked(signatureWithoutVersion, version) + ); } function testRecoverWithCorrectVersion() public { @@ -185,12 +197,20 @@ contract ECDSATest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signatureWithoutVersion = abi.encodePacked(r, s); - assertEq(alice, ECDSA.recover_sig(hash, abi.encodePacked(signatureWithoutVersion, v))); + assertEq( + alice, + ECDSA.recover_sig( + hash, + abi.encodePacked(signatureWithoutVersion, v) + ) + ); /** * @dev EIP-2098 signature check. */ - bytes memory signature2098 = to2098Format(abi.encodePacked(signatureWithoutVersion, v)); + bytes memory signature2098 = to2098Format( + abi.encodePacked(signatureWithoutVersion, v) + ); assertEq(alice, ECDSA.recover_sig(hash, signature2098)); } @@ -201,7 +221,8 @@ contract ECDSATest is Test { (, uint256 key) = makeAddrAndKey("alice"); bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); - uint256 sTooHigh = uint256(s) + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; + uint256 sTooHigh = uint256(s) + + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; bytes memory signature = abi.encodePacked(r, bytes32(sTooHigh), v); vm.expectRevert(bytes("ECDSA: invalid signature `s` value")); ECDSA.recover_sig(hash, signature); @@ -209,14 +230,18 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert(abi.encodeWithSelector(InvalidSignatureSValue.selector, self)); + vm.expectRevert( + abi.encodeWithSelector(InvalidSignatureSValue.selector, self) + ); to2098Format(signature); } function testEthSignedMessageHash() public { bytes32 hash = keccak256("WAGMI"); bytes32 digest1 = ECDSA.to_eth_signed_message_hash(hash); - bytes32 digest2 = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) + ); assertEq(digest1, digest2); } @@ -224,26 +249,38 @@ contract ECDSATest is Test { bytes32 domainSeparator = keccak256("WAGMI"); bytes32 structHash = keccak256("GM"); bytes32 digest1 = ECDSA.to_typed_data_hash(domainSeparator, structHash); - bytes32 digest2 = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x01", domainSeparator, structHash) + ); assertEq(digest1, digest2); } function testToDataWithIntendedValidatorHash() public { address validator = makeAddr("intendedValidator"); bytes memory data = new bytes(42); - bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash(validator, data); - bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", validator, data)); + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash( + validator, + data + ); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", validator, data) + ); assertEq(digest1, digest2); } function testToDataWithIntendedValidatorHashSelf() public { bytes memory data = new bytes(42); bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash_self(data); - bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", ECDSAAddr, data)); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", ECDSAAddr, data) + ); assertEq(digest1, digest2); } - function testFuzzRecoverWithValidSignature(string calldata signer, string calldata message) public { + function testFuzzRecoverWithValidSignature( + string calldata signer, + string calldata message + ) public { /** * @dev Standard signature check. */ @@ -260,7 +297,11 @@ contract ECDSATest is Test { assertEq(alice, ECDSA.recover_sig(hash, signature2098)); } - function testFuzzRecoverWithWrongMessage(string calldata signer, string calldata message, bytes32 digest) public { + function testFuzzRecoverWithWrongMessage( + string calldata signer, + string calldata message, + bytes32 digest + ) public { /** * @dev Standard signature check. */ @@ -278,7 +319,10 @@ contract ECDSATest is Test { assertTrue(alice != ECDSA.recover_sig(digest, signature2098)); } - function testFuzzRecoverWithInvalidSignature(bytes calldata signature, string calldata message) public { + function testFuzzRecoverWithInvalidSignature( + bytes calldata signature, + string calldata message + ) public { vm.assume(signature.length < 64); /** * @dev Standard signature check. @@ -290,11 +334,16 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); + vm.expectRevert( + abi.encodeWithSelector(InvalidSignatureLength.selector, self) + ); to2098Format(signature); } - function testFuzzRecoverWithTooLongSignature(bytes calldata signature, string calldata message) public { + function testFuzzRecoverWithTooLongSignature( + bytes calldata signature, + string calldata message + ) public { vm.assume(signature.length > 65); /** * @dev Standard signature check. @@ -306,34 +355,55 @@ contract ECDSATest is Test { /** * @dev EIP-2098 signature check. */ - vm.expectRevert(abi.encodeWithSelector(InvalidSignatureLength.selector, self)); + vm.expectRevert( + abi.encodeWithSelector(InvalidSignatureLength.selector, self) + ); to2098Format(signature); } function testFuzzEthSignedMessageHash(string calldata message) public { bytes32 hash = keccak256(abi.encode(message)); bytes32 digest1 = ECDSA.to_eth_signed_message_hash(hash); - bytes32 digest2 = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19Ethereum Signed Message:\n32", hash) + ); assertEq(digest1, digest2); } - function testFuzzToTypedDataHash(string calldata domainSeparatorPlain, string calldata structPlain) public { + function testFuzzToTypedDataHash( + string calldata domainSeparatorPlain, + string calldata structPlain + ) public { bytes32 domainSeparator = keccak256(abi.encode(domainSeparatorPlain)); bytes32 structHash = keccak256(abi.encode(structPlain)); bytes32 digest1 = ECDSA.to_typed_data_hash(domainSeparator, structHash); - bytes32 digest2 = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x01", domainSeparator, structHash) + ); assertEq(digest1, digest2); } - function testFuzzToDataWithIntendedValidatorHash(address validator, bytes calldata data) public { - bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash(validator, data); - bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", validator, data)); + function testFuzzToDataWithIntendedValidatorHash( + address validator, + bytes calldata data + ) public { + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash( + validator, + data + ); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", validator, data) + ); assertEq(digest1, digest2); } - function testFuzzToDataWithIntendedValidatorHashSelf(bytes calldata data) public { + function testFuzzToDataWithIntendedValidatorHashSelf( + bytes calldata data + ) public { bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash_self(data); - bytes32 digest2 = keccak256(abi.encodePacked("\x19\x00", ECDSAAddr, data)); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", ECDSAAddr, data) + ); assertEq(digest1, digest2); } } diff --git a/test/utils/EIP712DomainSeparator.t.sol b/test/utils/EIP712DomainSeparator.t.sol index c0d81c18..08c98f48 100644 --- a/test/utils/EIP712DomainSeparator.t.sol +++ b/test/utils/EIP712DomainSeparator.t.sol @@ -10,9 +10,17 @@ contract EIP712DomainSeparatorTest is Test { string private constant _NAME = "WAGMI"; string private constant _VERSION = "1"; bytes32 private constant _TYPE_HASH = - keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")); + keccak256( + bytes( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ) + ); bytes32 private constant _PERMIT_TYPE_HASH = - keccak256(bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")); + keccak256( + bytes( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ) + ); VyperDeployer private vyperDeployer = new VyperDeployer(); @@ -26,8 +34,13 @@ contract EIP712DomainSeparatorTest is Test { function setUp() public { bytes memory args = abi.encode(_NAME, _VERSION); - EIP712domainSeparator = - IEIP712DomainSeparator(vyperDeployer.deployContract("src/utils/", "EIP712DomainSeparator", args)); + EIP712domainSeparator = IEIP712DomainSeparator( + vyperDeployer.deployContract( + "src/utils/", + "EIP712DomainSeparator", + args + ) + ); EIP712domainSeparatorAddr = address(EIP712domainSeparator); _CACHED_DOMAIN_SEPARATOR = keccak256( abi.encode( @@ -41,7 +54,10 @@ contract EIP712DomainSeparatorTest is Test { } function testCachedDomainSeparatorV4() public { - assertEq(EIP712domainSeparator.domain_separator_v4(), _CACHED_DOMAIN_SEPARATOR); + assertEq( + EIP712domainSeparator.domain_separator_v4(), + _CACHED_DOMAIN_SEPARATOR + ); } function testDomainSeparatorV4() public { @@ -69,10 +85,24 @@ contract EIP712DomainSeparatorTest is Test { uint256 nonce = 1; // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; - bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, value, nonce, deadline)); + bytes32 structHash = keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + value, + nonce, + deadline + ) + ); bytes32 digest1 = EIP712domainSeparator.hash_typed_data_v4(structHash); - bytes32 digest2 = - keccak256(abi.encodePacked("\x19\x01", EIP712domainSeparator.domain_separator_v4(), structHash)); + bytes32 digest2 = keccak256( + abi.encodePacked( + "\x19\x01", + EIP712domainSeparator.domain_separator_v4(), + structHash + ) + ); assertEq(digest1, digest2); } @@ -95,7 +125,13 @@ contract EIP712DomainSeparatorTest is Test { assertEq(extensions, new uint256[](0)); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(EIP712domainSeparator.domain_separator_v4(), digest); } @@ -118,15 +154,33 @@ contract EIP712DomainSeparatorTest is Test { assertEq(EIP712domainSeparator.domain_separator_v4(), digest); } - function testFuzzHashTypedDataV4(address owner, address spender, uint256 value, uint256 nonce, uint64 increment) - public - { + function testFuzzHashTypedDataV4( + address owner, + address spender, + uint256 value, + uint256 nonce, + uint64 increment + ) public { // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; - bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, value, nonce, deadline)); + bytes32 structHash = keccak256( + abi.encode( + _PERMIT_TYPE_HASH, + owner, + spender, + value, + nonce, + deadline + ) + ); bytes32 digest1 = EIP712domainSeparator.hash_typed_data_v4(structHash); - bytes32 digest2 = - keccak256(abi.encodePacked("\x19\x01", EIP712domainSeparator.domain_separator_v4(), structHash)); + bytes32 digest2 = keccak256( + abi.encodePacked( + "\x19\x01", + EIP712domainSeparator.domain_separator_v4(), + structHash + ) + ); assertEq(digest1, digest2); } @@ -136,7 +190,11 @@ contract EIP712DomainSeparatorTest is Test { bytes32 randomSalt, uint256[] calldata randomExtensions ) public { - vm.assume(randomHex != hex"0f" && randomSalt != bytes32(0) && randomExtensions.length != 0); + vm.assume( + randomHex != hex"0f" && + randomSalt != bytes32(0) && + randomExtensions.length != 0 + ); vm.chainId(block.chainid + increment); ( bytes1 fields, @@ -153,10 +211,19 @@ contract EIP712DomainSeparatorTest is Test { assertEq(chainId, block.chainid); assertEq(verifyingContract, EIP712domainSeparatorAddr); assertTrue(salt != randomSalt); - assertTrue(keccak256(abi.encode(extensions)) != keccak256(abi.encode(randomExtensions))); + assertTrue( + keccak256(abi.encode(extensions)) != + keccak256(abi.encode(randomExtensions)) + ); bytes32 digest = keccak256( - abi.encode(_TYPE_HASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, verifyingContract) + abi.encode( + _TYPE_HASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + verifyingContract + ) ); assertEq(EIP712domainSeparator.domain_separator_v4(), digest); } diff --git a/test/utils/Math.t.sol b/test/utils/Math.t.sol index e2ca5032..325f911d 100644 --- a/test/utils/Math.t.sol +++ b/test/utils/Math.t.sol @@ -23,7 +23,11 @@ contract MathTest is Test { * @param denominator The 32-byte divisor. * @return result The 32-byte result of the `mulmod` operation. */ - function mulMod(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { + function mulMod( + uint256 x, + uint256 y, + uint256 denominator + ) internal pure returns (uint256 result) { // solhint-disable-next-line no-inline-assembly assembly { result := mulmod(x, y, denominator) @@ -38,7 +42,10 @@ contract MathTest is Test { * @return high The most significant 32 bytes of the product. * @return low The least significant 32 bytes of the product. */ - function mulHighLow(uint256 x, uint256 y) internal pure returns (uint256 high, uint256 low) { + function mulHighLow( + uint256 x, + uint256 y + ) internal pure returns (uint256 high, uint256 low) { (uint256 x0, uint256 x1) = (x & type(uint128).max, x >> 128); (uint256 y0, uint256 y1) = (y & type(uint128).max, y >> 128); @@ -50,7 +57,9 @@ contract MathTest is Test { uint256 z1b = x0 * y1; uint256 z0 = x0 * y0; - uint256 carry = ((z1a & type(uint128).max) + (z1b & type(uint128).max) + (z0 >> 128)) >> 128; + uint256 carry = ((z1a & type(uint128).max) + + (z1b & type(uint128).max) + + (z0 >> 128)) >> 128; high = z2 + (z1a >> 128) + (z1b >> 128) + carry; @@ -67,7 +76,10 @@ contract MathTest is Test { * @return remainder The 32-byte remainder. * @return carry The 32-byte carry. */ - function addCarry(uint256 x, uint256 y) internal pure returns (uint256 remainder, uint256 carry) { + function addCarry( + uint256 x, + uint256 y + ) internal pure returns (uint256 remainder, uint256 carry) { unchecked { remainder = x + y; } @@ -106,7 +118,10 @@ contract MathTest is Test { assertEq(math.uint256_average(73_220, 419_712), 246_466); assertEq(math.uint256_average(83_219, 419_712), 251_465); assertEq(math.uint256_average(73_220, 219_713), 146_466); - assertEq(math.uint256_average(type(uint256).max, type(uint256).max), type(uint256).max); + assertEq( + math.uint256_average(type(uint256).max, type(uint256).max), + type(uint256).max + ); } function testInt256Average() public { @@ -122,7 +137,10 @@ contract MathTest is Test { assertEq(math.int256_average(73_220, 219_713), 146_466); assertEq(math.int256_average(-73_220, -219_713), -146_467); - assertEq(math.int256_average(type(int256).min, type(int256).min), type(int256).min); + assertEq( + math.int256_average(type(int256).min, type(int256).min), + type(int256).min + ); assertEq(math.int256_average(type(int256).min, type(int256).max), -1); } @@ -174,9 +192,18 @@ contract MathTest is Test { uint256 maxUint256Sub2 = maxUint256 - 2; assertEq(math.mul_div(42, maxUint256Sub1, maxUint256, false), 41); assertEq(math.mul_div(23, maxUint256, maxUint256, false), 23); - assertEq(math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, false), maxUint256Sub2); - assertEq(math.mul_div(maxUint256, maxUint256Sub1, maxUint256, false), maxUint256Sub1); - assertEq(math.mul_div(maxUint256, maxUint256, maxUint256, false), maxUint256); + assertEq( + math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, false), + maxUint256Sub2 + ); + assertEq( + math.mul_div(maxUint256, maxUint256Sub1, maxUint256, false), + maxUint256Sub1 + ); + assertEq( + math.mul_div(maxUint256, maxUint256, maxUint256, false), + maxUint256 + ); } function testMulDivRoundUpSmallValues() public { @@ -190,9 +217,18 @@ contract MathTest is Test { uint256 maxUint256Sub1 = maxUint256 - 1; assertEq(math.mul_div(42, maxUint256Sub1, maxUint256, true), 42); assertEq(math.mul_div(23, maxUint256, maxUint256, true), 23); - assertEq(math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, true), maxUint256Sub1); - assertEq(math.mul_div(maxUint256, maxUint256Sub1, maxUint256, true), maxUint256Sub1); - assertEq(math.mul_div(maxUint256, maxUint256, maxUint256, true), maxUint256); + assertEq( + math.mul_div(maxUint256Sub1, maxUint256Sub1, maxUint256, true), + maxUint256Sub1 + ); + assertEq( + math.mul_div(maxUint256, maxUint256Sub1, maxUint256, true), + maxUint256Sub1 + ); + assertEq( + math.mul_div(maxUint256, maxUint256, maxUint256, true), + maxUint256 + ); } function testLog2RoundDown() public { @@ -288,8 +324,14 @@ contract MathTest is Test { assertEq(math.wad_ln(42), -37_708_862_055_609_454_007); assertEq(math.wad_ln(10 ** 4), -32_236_191_301_916_639_577); assertEq(math.wad_ln(10 ** 9), -20_723_265_836_946_411_157); - assertEq(math.wad_ln(2_718_281_828_459_045_235), 999_999_999_999_999_999); - assertEq(math.wad_ln(11_723_640_096_265_400_935), 2_461_607_324_344_817_918); + assertEq( + math.wad_ln(2_718_281_828_459_045_235), + 999_999_999_999_999_999 + ); + assertEq( + math.wad_ln(11_723_640_096_265_400_935), + 2_461_607_324_344_817_918 + ); assertEq(math.wad_ln(2 ** 128), 47_276_307_437_780_177_293); assertEq(math.wad_ln(2 ** 170), 76_388_489_021_297_880_288); assertEq(math.wad_ln(type(int256).max), 135_305_999_368_893_231_589); @@ -317,7 +359,10 @@ contract MathTest is Test { assertEq(math.wad_exp(2 * 10 ** 18), 7_389_056_098_930_650_227); assertEq(math.wad_exp(3 * 10 ** 18), 20_085_536_923_187_667_741); assertEq(math.wad_exp(10 * 10 ** 18), 22_026_465_794_806_716_516_980); - assertEq(math.wad_exp(50 * 10 ** 18), 5_184_705_528_587_072_464_148_529_318_587_763_226_117); + assertEq( + math.wad_exp(50 * 10 ** 18), + 5_184_705_528_587_072_464_148_529_318_587_763_226_117 + ); assertEq( math.wad_exp(100 * 10 ** 18), 26_881_171_418_161_354_484_134_666_106_240_937_146_178_367_581_647_816_351_662_017 @@ -352,7 +397,10 @@ contract MathTest is Test { assertEq(math.cbrt(type(uint32).max, false), 1_625); assertEq(math.cbrt(type(uint64).max, false), 2_642_245); assertEq(math.cbrt(type(uint128).max, false), 6_981_463_658_331); - assertEq(math.cbrt(type(uint256).max, false), 48_740_834_812_604_276_470_692_694); + assertEq( + math.cbrt(type(uint256).max, false), + 48_740_834_812_604_276_470_692_694 + ); } function testCbrtRoundUp() public { @@ -372,7 +420,10 @@ contract MathTest is Test { assertEq(math.cbrt(type(uint32).max, true), 1_626); assertEq(math.cbrt(type(uint64).max, true), 2_642_246); assertEq(math.cbrt(type(uint128).max, true), 6_981_463_658_332); - assertEq(math.cbrt(type(uint256).max, true), 48_740_834_812_604_276_470_692_695); + assertEq( + math.cbrt(type(uint256).max, true), + 48_740_834_812_604_276_470_692_695 + ); } function testWadCbrt() public { @@ -391,8 +442,14 @@ contract MathTest is Test { assertEq(math.wad_cbrt(type(uint16).max), 40_317_268_530_317); assertEq(math.wad_cbrt(type(uint32).max), 1_625_498_677_089_280); assertEq(math.wad_cbrt(type(uint64).max), 2_642_245_949_629_133_047); - assertEq(math.wad_cbrt(type(uint128).max), 6_981_463_658_331_559_092_288_464); - assertEq(math.wad_cbrt(type(uint256).max), 48_740_834_812_604_276_470_692_694_000_000_000_000); + assertEq( + math.wad_cbrt(type(uint128).max), + 6_981_463_658_331_559_092_288_464 + ); + assertEq( + math.wad_cbrt(type(uint256).max), + 48_740_834_812_604_276_470_692_694_000_000_000_000 + ); } /** @@ -484,7 +541,7 @@ contract MathTest is Test { * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/test/utils/math/Math.t.sol. */ function testFuzzMulDivDomain(uint256 x, uint256 y, uint256 d) public { - (uint256 xyHi,) = mulHighLow(x, y); + (uint256 xyHi, ) = mulHighLow(x, y); /** * @dev Violate `testFuzzMulDiv` assumption, i.e. `d` is 0 and result overflows. @@ -598,7 +655,9 @@ contract MathTest is Test { function testFuzzWadCbrt(uint256 x) public { uint256 result = math.wad_cbrt(x); uint256 floor = floorCbrt(x); - assertTrue(result >= floor * 10 ** 12 && result <= (floor + 1) * 10 ** 12); + assertTrue( + result >= floor * 10 ** 12 && result <= (floor + 1) * 10 ** 12 + ); assertEq(result / 10 ** 12, floor); } } diff --git a/test/utils/MerkleProofVerification.t.sol b/test/utils/MerkleProofVerification.t.sol index 478e5f82..e5cd347e 100644 --- a/test/utils/MerkleProofVerification.t.sol +++ b/test/utils/MerkleProofVerification.t.sol @@ -27,8 +27,17 @@ contract MerkleProofVerificationTest is Test { cmdsProof[0] = "node"; cmdsProof[1] = "test/utils/scripts/generate-proof.js"; bytes memory proof = vm.ffi(cmdsProof); - (bytes32 arg1, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5, bytes32 arg6) = - abi.decode(proof, (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32)); + ( + bytes32 arg1, + bytes32 arg2, + bytes32 arg3, + bytes32 arg4, + bytes32 arg5, + bytes32 arg6 + ) = abi.decode( + proof, + (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32) + ); proofDecoded[0] = arg1; proofDecoded[1] = arg2; proofDecoded[2] = arg3; @@ -45,14 +54,37 @@ contract MerkleProofVerificationTest is Test { * @return bytes32[] The 32-byte array containing sibling hashes * on the branches from `leaves` to the `root` of the Merkle tree. */ - function decodeCorrectMultiProofPayload() internal returns (bytes32[] memory) { + function decodeCorrectMultiProofPayload() + internal + returns (bytes32[] memory) + { bytes32[] memory multiProofDecoded = new bytes32[](8); string[] memory cmdsMultiProof = new string[](2); cmdsMultiProof[0] = "node"; cmdsMultiProof[1] = "test/utils/scripts/generate-multiproof.js"; bytes memory multiProof = vm.ffi(cmdsMultiProof); - (bytes32 arg1, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5, bytes32 arg6, bytes32 arg7, bytes32 arg8) - = abi.decode(multiProof, (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32)); + ( + bytes32 arg1, + bytes32 arg2, + bytes32 arg3, + bytes32 arg4, + bytes32 arg5, + bytes32 arg6, + bytes32 arg7, + bytes32 arg8 + ) = abi.decode( + multiProof, + ( + bytes32, + bytes32, + bytes32, + bytes32, + bytes32, + bytes32, + bytes32, + bytes32 + ) + ); multiProofDecoded[0] = arg1; multiProofDecoded[1] = arg2; multiProofDecoded[2] = arg3; @@ -72,14 +104,32 @@ contract MerkleProofVerificationTest is Test { * value from the "main queue" (merging branches) or an element from the * `proof` array is used to calculate the next hash. */ - function decodeCorrectMultiProofProofFlags() internal returns (bool[] memory) { + function decodeCorrectMultiProofProofFlags() + internal + returns (bool[] memory) + { bool[] memory multiProofProofFlagsDecoded = new bool[](10); string[] memory cmdsMultiProofProofFlags = new string[](2); cmdsMultiProofProofFlags[0] = "node"; - cmdsMultiProofProofFlags[1] = "test/utils/scripts/generate-multiproof-proof-flags.js"; + cmdsMultiProofProofFlags[ + 1 + ] = "test/utils/scripts/generate-multiproof-proof-flags.js"; bytes memory multiProofProofFlags = vm.ffi(cmdsMultiProofProofFlags); - (bool arg1, bool arg2, bool arg3, bool arg4, bool arg5, bool arg6, bool arg7, bool arg8, bool arg9, bool arg10) - = abi.decode(multiProofProofFlags, (bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)); + ( + bool arg1, + bool arg2, + bool arg3, + bool arg4, + bool arg5, + bool arg6, + bool arg7, + bool arg8, + bool arg9, + bool arg10 + ) = abi.decode( + multiProofProofFlags, + (bool, bool, bool, bool, bool, bool, bool, bool, bool, bool) + ); multiProofProofFlagsDecoded[0] = arg1; multiProofProofFlagsDecoded[1] = arg2; multiProofProofFlagsDecoded[2] = arg3; @@ -103,14 +153,27 @@ contract MerkleProofVerificationTest is Test { * @return bytes32[] The 32-byte array containing sibling hashes * on the branch from the `leaf` to the `root` of the Merkle tree. */ - function decodeNoSuchLeafProofPayload() internal returns (bytes32[] memory) { + function decodeNoSuchLeafProofPayload() + internal + returns (bytes32[] memory) + { bytes32[] memory proofDecodedSliced = new bytes32[](6); string[] memory cmdsProof = new string[](2); cmdsProof[0] = "node"; cmdsProof[1] = "test/utils/scripts/generate-proof-no-such-leaf.js"; bytes memory proof = vm.ffi(cmdsProof); - (, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5, bytes32 arg6, bytes32 arg7) = - abi.decode(proof, (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32)); + ( + , + bytes32 arg2, + bytes32 arg3, + bytes32 arg4, + bytes32 arg5, + bytes32 arg6, + bytes32 arg7 + ) = abi.decode( + proof, + (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32) + ); proofDecodedSliced[0] = arg2; proofDecodedSliced[1] = arg3; proofDecodedSliced[2] = arg4; @@ -153,8 +216,16 @@ contract MerkleProofVerificationTest is Test { cmdsMultiProof[0] = "node"; cmdsMultiProof[1] = "test/utils/scripts/generate-bad-multiproof.js"; bytes memory multiProof = vm.ffi(cmdsMultiProof); - (bytes32 arg1, bytes32 arg2, bytes32 arg3, bytes32 arg4, bytes32 arg5) = - abi.decode(multiProof, (bytes32, bytes32, bytes32, bytes32, bytes32)); + ( + bytes32 arg1, + bytes32 arg2, + bytes32 arg3, + bytes32 arg4, + bytes32 arg5 + ) = abi.decode( + multiProof, + (bytes32, bytes32, bytes32, bytes32, bytes32) + ); multiProofDecoded[0] = arg1; multiProofDecoded[1] = arg2; multiProofDecoded[2] = arg3; @@ -177,10 +248,22 @@ contract MerkleProofVerificationTest is Test { bool[] memory multiProofProofFlagsDecoded = new bool[](7); string[] memory cmdsMultiProofProofFlags = new string[](2); cmdsMultiProofProofFlags[0] = "node"; - cmdsMultiProofProofFlags[1] = "test/utils/scripts/generate-bad-multiproof-proof-flags.js"; + cmdsMultiProofProofFlags[ + 1 + ] = "test/utils/scripts/generate-bad-multiproof-proof-flags.js"; bytes memory multiProofProofFlags = vm.ffi(cmdsMultiProofProofFlags); - (bool arg1, bool arg2, bool arg3, bool arg4, bool arg5, bool arg6, bool arg7) = - abi.decode(multiProofProofFlags, (bool, bool, bool, bool, bool, bool, bool)); + ( + bool arg1, + bool arg2, + bool arg3, + bool arg4, + bool arg5, + bool arg6, + bool arg7 + ) = abi.decode( + multiProofProofFlags, + (bool, bool, bool, bool, bool, bool, bool) + ); multiProofProofFlagsDecoded[0] = arg1; multiProofProofFlagsDecoded[1] = arg2; multiProofProofFlagsDecoded[2] = arg3; @@ -192,8 +275,12 @@ contract MerkleProofVerificationTest is Test { } function setUp() public { - merkleProofVerification = - IMerkleProofVerification(vyperDeployer.deployContract("src/utils/", "MerkleProofVerification")); + merkleProofVerification = IMerkleProofVerification( + vyperDeployer.deployContract( + "src/utils/", + "MerkleProofVerification" + ) + ); } function testVerify() public { @@ -209,11 +296,19 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory proofDecoded = decodeCorrectProofPayload(); - assertTrue(merkleProofVerification.verify(proofDecoded, bytes32(root), bytes32(leaf))); + assertTrue( + merkleProofVerification.verify( + proofDecoded, + bytes32(root), + bytes32(leaf) + ) + ); string[] memory cmdsRootNoSuchLeaf = new string[](2); cmdsRootNoSuchLeaf[0] = "node"; - cmdsRootNoSuchLeaf[1] = "test/utils/scripts/generate-root-no-such-leaf.js"; + cmdsRootNoSuchLeaf[ + 1 + ] = "test/utils/scripts/generate-root-no-such-leaf.js"; bytes memory rootNoSuchLeaf = vm.ffi(cmdsRootNoSuchLeaf); string[] memory cmdsNoSuchLeaf = new string[](2); @@ -223,7 +318,13 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory proofDecodedSliced = decodeNoSuchLeafProofPayload(); - assertTrue(merkleProofVerification.verify(proofDecodedSliced, bytes32(rootNoSuchLeaf), bytes32(noSuchLeaf))); + assertTrue( + merkleProofVerification.verify( + proofDecodedSliced, + bytes32(rootNoSuchLeaf), + bytes32(noSuchLeaf) + ) + ); } function testInvalidMerkleProof() public { @@ -239,7 +340,13 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory badProofDecoded = decodeBadProofPayload(); - assertTrue(!merkleProofVerification.verify(badProofDecoded, bytes32(correctRoot), bytes32(leaf))); + assertTrue( + !merkleProofVerification.verify( + badProofDecoded, + bytes32(correctRoot), + bytes32(leaf) + ) + ); } function testInvalidMerkleProofLength() public { @@ -260,7 +367,13 @@ contract MerkleProofVerificationTest is Test { proofInvalidLengthDecoded[1] = proofDecoded[1]; proofInvalidLengthDecoded[2] = proofDecoded[2]; - assertTrue(!merkleProofVerification.verify(proofInvalidLengthDecoded, bytes32(root), bytes32(leaf))); + assertTrue( + !merkleProofVerification.verify( + proofInvalidLengthDecoded, + bytes32(root), + bytes32(leaf) + ) + ); } function testMultiProofVerify() public { @@ -274,7 +387,10 @@ contract MerkleProofVerificationTest is Test { cmdsLeaves[1] = "test/utils/scripts/generate-multiproof-leaves.js"; bytes memory leaves = vm.ffi(cmdsLeaves); bytes32[] memory leavesDecoded = new bytes32[](3); - (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode(leaves, (bytes32, bytes32, bytes32)); + (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode( + leaves, + (bytes32, bytes32, bytes32) + ); leavesDecoded[0] = arg1; leavesDecoded[1] = arg2; leavesDecoded[2] = arg3; @@ -283,7 +399,12 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory multiProofDecoded = decodeCorrectMultiProofPayload(); assertTrue( - merkleProofVerification.multi_proof_verify(multiProofDecoded, proofFlags, bytes32(root), leavesDecoded) + merkleProofVerification.multi_proof_verify( + multiProofDecoded, + proofFlags, + bytes32(root), + leavesDecoded + ) ); } @@ -295,10 +416,15 @@ contract MerkleProofVerificationTest is Test { string[] memory cmdsBadLeaves = new string[](2); cmdsBadLeaves[0] = "node"; - cmdsBadLeaves[1] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; + cmdsBadLeaves[ + 1 + ] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; bytes memory badLeaves = vm.ffi(cmdsBadLeaves); bytes32[] memory badLeavesDecoded = new bytes32[](3); - (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode(badLeaves, (bytes32, bytes32, bytes32)); + (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode( + badLeaves, + (bytes32, bytes32, bytes32) + ); badLeavesDecoded[0] = arg1; badLeavesDecoded[1] = arg2; badLeavesDecoded[2] = arg3; @@ -308,7 +434,10 @@ contract MerkleProofVerificationTest is Test { assertTrue( !merkleProofVerification.multi_proof_verify( - badMultiProofDecoded, badProofFlags, bytes32(correctRoot), badLeavesDecoded + badMultiProofDecoded, + badProofFlags, + bytes32(correctRoot), + badLeavesDecoded ) ); } @@ -347,7 +476,12 @@ contract MerkleProofVerificationTest is Test { maliciousProofFlags[2] = false; vm.expectRevert(); - merkleProofVerification.multi_proof_verify(maliciousProof, maliciousProofFlags, root, maliciousLeaves); + merkleProofVerification.multi_proof_verify( + maliciousProof, + maliciousProofFlags, + root, + maliciousLeaves + ); } function testInvalidMultiProof() public { @@ -358,10 +492,15 @@ contract MerkleProofVerificationTest is Test { string[] memory cmdsBadLeaves = new string[](2); cmdsBadLeaves[0] = "node"; - cmdsBadLeaves[1] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; + cmdsBadLeaves[ + 1 + ] = "test/utils/scripts/generate-bad-multiproof-leaves.js"; bytes memory badLeaves = vm.ffi(cmdsBadLeaves); bytes32[] memory badLeavesDecoded = new bytes32[](3); - (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode(badLeaves, (bytes32, bytes32, bytes32)); + (bytes32 arg1, bytes32 arg2, bytes32 arg3) = abi.decode( + badLeaves, + (bytes32, bytes32, bytes32) + ); badLeavesDecoded[0] = arg1; badLeavesDecoded[1] = arg2; badLeavesDecoded[2] = arg3; @@ -385,17 +524,26 @@ contract MerkleProofVerificationTest is Test { vm.expectRevert(bytes("MerkleProof: invalid multiproof")); merkleProofVerification.multi_proof_verify( - badMultiProofDecodedSliced, badProofFlags, bytes32(correctRoot), badLeavesDecoded + badMultiProofDecodedSliced, + badProofFlags, + bytes32(correctRoot), + badLeavesDecoded ); vm.expectRevert(bytes("MerkleProof: invalid multiproof")); merkleProofVerification.multi_proof_verify( - badMultiProofDecoded, badProofFlagsSliced, bytes32(correctRoot), badLeavesDecoded + badMultiProofDecoded, + badProofFlagsSliced, + bytes32(correctRoot), + badLeavesDecoded ); vm.expectRevert(bytes("MerkleProof: invalid multiproof")); merkleProofVerification.multi_proof_verify( - badMultiProofDecoded, badProofFlags, bytes32(correctRoot), badLeavesDecodedSliced + badMultiProofDecoded, + badProofFlags, + bytes32(correctRoot), + badLeavesDecodedSliced ); } @@ -409,7 +557,14 @@ contract MerkleProofVerificationTest is Test { /** * @dev Works for a Merkle tree containing a single leaf. */ - assertTrue(merkleProofVerification.multi_proof_verify(multiProof, proofFlags, leaves[0], leaves)); + assertTrue( + merkleProofVerification.multi_proof_verify( + multiProof, + proofFlags, + leaves[0], + leaves + ) + ); } function testMultiProofEdgeCase2() public { @@ -417,38 +572,65 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory multiProof = new bytes32[](1); bool[] memory proofFlags = new bool[](0); - bytes32 root = keccak256(bytes.concat(keccak256(abi.encode("a", "b", "c")))); + bytes32 root = keccak256( + bytes.concat(keccak256(abi.encode("a", "b", "c"))) + ); multiProof[0] = root; /** * @dev Can prove empty leaves. */ - assertTrue(merkleProofVerification.multi_proof_verify(multiProof, proofFlags, root, leaves)); + assertTrue( + merkleProofVerification.multi_proof_verify( + multiProof, + proofFlags, + root, + leaves + ) + ); } /** * @notice Forked and adjusted accordingly from here: * https://github.com/Vectorized/solady/blob/main/test/MerkleProofLib.t.sol. */ - function testFuzzVerify(bytes32[] calldata data, uint256 randomness) public { + function testFuzzVerify( + bytes32[] calldata data, + uint256 randomness + ) public { vm.assume(data.length > 1); uint256 nodeIndex = randomness % data.length; bytes32 root = merkleGenerator.getRoot(data); bytes32[] memory proof = merkleGenerator.getProof(data, nodeIndex); bytes32 leaf = data[nodeIndex]; assertTrue(merkleProofVerification.verify(proof, root, leaf)); - assertTrue(!merkleProofVerification.verify(proof, bytes32(uint256(root) ^ 1), leaf)); + assertTrue( + !merkleProofVerification.verify( + proof, + bytes32(uint256(root) ^ 1), + leaf + ) + ); proof[0] = bytes32(uint256(proof[0]) ^ 1); assertTrue(!merkleProofVerification.verify(proof, root, leaf)); - assertTrue(!merkleProofVerification.verify(proof, bytes32(uint256(root) ^ 1), leaf)); + assertTrue( + !merkleProofVerification.verify( + proof, + bytes32(uint256(root) ^ 1), + leaf + ) + ); } /** * @notice Forked and adjusted accordingly from here: * https://github.com/Vectorized/solady/blob/main/test/MerkleProofLib.t.sol. */ - function testFuzzMultiProofVerifySingleLeaf(bytes32[] calldata data, uint256 randomness) public { + function testFuzzMultiProofVerifySingleLeaf( + bytes32[] calldata data, + uint256 randomness + ) public { vm.assume(data.length > 1); uint256 nodeIndex = randomness % data.length; bytes32 root = merkleGenerator.getRoot(data); @@ -456,19 +638,51 @@ contract MerkleProofVerificationTest is Test { bytes32[] memory leaves = new bytes32[](1); leaves[0] = data[nodeIndex]; bool[] memory proofFlags = new bool[](proof.length); - assertTrue(merkleProofVerification.multi_proof_verify(proof, proofFlags, root, leaves)); - assertTrue(!merkleProofVerification.multi_proof_verify(proof, proofFlags, bytes32(uint256(root) ^ 1), leaves)); + assertTrue( + merkleProofVerification.multi_proof_verify( + proof, + proofFlags, + root, + leaves + ) + ); + assertTrue( + !merkleProofVerification.multi_proof_verify( + proof, + proofFlags, + bytes32(uint256(root) ^ 1), + leaves + ) + ); proof[0] = bytes32(uint256(proof[0]) ^ 1); - assertTrue(!merkleProofVerification.multi_proof_verify(proof, proofFlags, root, leaves)); - assertTrue(!merkleProofVerification.multi_proof_verify(proof, proofFlags, bytes32(uint256(root) ^ 1), leaves)); + assertTrue( + !merkleProofVerification.multi_proof_verify( + proof, + proofFlags, + root, + leaves + ) + ); + assertTrue( + !merkleProofVerification.multi_proof_verify( + proof, + proofFlags, + bytes32(uint256(root) ^ 1), + leaves + ) + ); } /** * @notice Forked and adjusted accordingly from here: * https://github.com/Vectorized/solady/blob/main/test/MerkleProofLib.t.sol. */ - function testFuzzVerifyMultiProofMultipleLeaves(bool damageProof, bool damageRoot, bool damageLeaves) public { + function testFuzzVerifyMultiProofMultipleLeaves( + bool damageProof, + bool damageRoot, + bool damageLeaves + ) public { bool noDamage = true; bytes32 root = merkleGenerator.hashLeafPairs( @@ -509,6 +723,14 @@ contract MerkleProofVerificationTest is Test { proof[0] = bytes32(uint256(proof[0]) ^ 1); } - assertEq(merkleProofVerification.multi_proof_verify(proof, flags, root, leaves), noDamage); + assertEq( + merkleProofVerification.multi_proof_verify( + proof, + flags, + root, + leaves + ), + noDamage + ); } } diff --git a/test/utils/Multicall.t.sol b/test/utils/Multicall.t.sol index df051faf..62b7294d 100644 --- a/test/utils/Multicall.t.sol +++ b/test/utils/Multicall.t.sol @@ -20,52 +20,108 @@ contract MulticallTest is Test { address private mockCalleeAddr = address(mockCallee); function setUp() public { - multicall = IMulticall(vyperDeployer.deployContract("src/utils/", "Multicall")); + multicall = IMulticall( + vyperDeployer.deployContract("src/utils/", "Multicall") + ); } function testMulticallSuccess() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](3); - batch[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch[1] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); - batch[2] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); + batch[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch[1] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("store(uint256)", type(uint256).max) + ); + batch[2] = IMulticall.Batch( + mockCalleeAddr, + true, + abi.encodeWithSignature("thisMethodReverts()") + ); IMulticall.Result[] memory results = multicall.multicall(batch); assertTrue(results[0].success); - assertEq(keccak256(results[0].returnData), keccak256(abi.encodePacked(blockhash(block.number)))); - assertEq(keccak256(results[1].returnData), keccak256(abi.encodePacked(abi.encode(true)))); + assertEq( + keccak256(results[0].returnData), + keccak256(abi.encodePacked(blockhash(block.number))) + ); + assertEq( + keccak256(results[1].returnData), + keccak256(abi.encodePacked(abi.encode(true))) + ); assertEq(mockCallee.number(), type(uint256).max); assertTrue(!results[2].success); } function testMulticallRevert() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](3); - batch[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch[1] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); - batch[2] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("thisMethodReverts()")); + batch[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch[1] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("store(uint256)", type(uint256).max) + ); + batch[2] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("thisMethodReverts()") + ); - vm.expectRevert(abi.encodeWithSelector(Reverted.selector, mockCalleeAddr)); + vm.expectRevert( + abi.encodeWithSelector(Reverted.selector, mockCalleeAddr) + ); multicall.multicall(batch); } function testMulticallValueSuccess() public { - IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[](4); + IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[]( + 4 + ); batchValue[0] = IMulticall.BatchValue( - mockCalleeAddr, false, 0, abi.encodeWithSignature("getBlockHash(uint256)", block.number) + mockCalleeAddr, + false, + 0, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) ); batchValue[1] = IMulticall.BatchValue( - mockCalleeAddr, false, 0, abi.encodeWithSignature("store(uint256)", type(uint256).max) + mockCalleeAddr, + false, + 0, + abi.encodeWithSignature("store(uint256)", type(uint256).max) + ); + batchValue[2] = IMulticall.BatchValue( + mockCalleeAddr, + true, + 0, + abi.encodeWithSignature("thisMethodReverts()") ); - batchValue[2] = IMulticall.BatchValue(mockCalleeAddr, true, 0, abi.encodeWithSignature("thisMethodReverts()")); batchValue[3] = IMulticall.BatchValue( - mockCalleeAddr, false, 1, abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) + mockCalleeAddr, + false, + 1, + abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) ); - IMulticall.Result[] memory results = multicall.multicall_value{value: 1}(batchValue); + IMulticall.Result[] memory results = multicall.multicall_value{ + value: 1 + }(batchValue); assertTrue(results[0].success); - assertEq(keccak256(results[0].returnData), keccak256(abi.encodePacked(blockhash(block.number)))); - assertEq(keccak256(results[1].returnData), keccak256(abi.encodePacked(abi.encode(true)))); + assertEq( + keccak256(results[0].returnData), + keccak256(abi.encodePacked(blockhash(block.number))) + ); + assertEq( + keccak256(results[1].returnData), + keccak256(abi.encodePacked(abi.encode(true))) + ); assertEq(mockCallee.number(), type(uint256).max); assertEq(etherReceiverAddr.balance, 1 wei); assertTrue(!results[2].success); @@ -73,36 +129,70 @@ contract MulticallTest is Test { } function testMulticallValueRevertCase1() public { - IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[](4); + IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[]( + 4 + ); batchValue[0] = IMulticall.BatchValue( - mockCalleeAddr, false, 0, abi.encodeWithSignature("getBlockHash(uint256)", block.number) + mockCalleeAddr, + false, + 0, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) ); batchValue[1] = IMulticall.BatchValue( - mockCalleeAddr, false, 0, abi.encodeWithSignature("store(uint256)", type(uint256).max) + mockCalleeAddr, + false, + 0, + abi.encodeWithSignature("store(uint256)", type(uint256).max) ); /** * @dev We don't allow for a failure. */ - batchValue[2] = IMulticall.BatchValue(mockCalleeAddr, false, 0, abi.encodeWithSignature("thisMethodReverts()")); + batchValue[2] = IMulticall.BatchValue( + mockCalleeAddr, + false, + 0, + abi.encodeWithSignature("thisMethodReverts()") + ); batchValue[3] = IMulticall.BatchValue( - mockCalleeAddr, false, 1, abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) + mockCalleeAddr, + false, + 1, + abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) ); - vm.expectRevert(abi.encodeWithSelector(Reverted.selector, mockCalleeAddr)); + vm.expectRevert( + abi.encodeWithSelector(Reverted.selector, mockCalleeAddr) + ); multicall.multicall_value{value: 1}(batchValue); } function testMulticallValueRevertCase2() public { - IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[](4); + IMulticall.BatchValue[] memory batchValue = new IMulticall.BatchValue[]( + 4 + ); batchValue[0] = IMulticall.BatchValue( - mockCalleeAddr, false, 0, abi.encodeWithSignature("getBlockHash(uint256)", block.number) + mockCalleeAddr, + false, + 0, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) ); batchValue[1] = IMulticall.BatchValue( - mockCalleeAddr, false, 0, abi.encodeWithSignature("store(uint256)", type(uint256).max) + mockCalleeAddr, + false, + 0, + abi.encodeWithSignature("store(uint256)", type(uint256).max) + ); + batchValue[2] = IMulticall.BatchValue( + mockCalleeAddr, + true, + 0, + abi.encodeWithSignature("thisMethodReverts()") ); - batchValue[2] = IMulticall.BatchValue(mockCalleeAddr, true, 0, abi.encodeWithSignature("thisMethodReverts()")); batchValue[3] = IMulticall.BatchValue( - mockCalleeAddr, true, 1, abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) + mockCalleeAddr, + true, + 1, + abi.encodeWithSignature("transferEther(address)", etherReceiverAddr) ); vm.expectRevert(bytes("Multicall: value mismatch")); @@ -114,23 +204,50 @@ contract MulticallTest is Test { function testMulticallSelfSuccess() public { IMulticall.Batch[] memory batch1 = new IMulticall.Batch[](3); - batch1[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch1[1] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); - batch1[2] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); + batch1[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch1[1] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("store(uint256)", type(uint256).max) + ); + batch1[2] = IMulticall.Batch( + mockCalleeAddr, + true, + abi.encodeWithSignature("thisMethodReverts()") + ); IMulticall.Batch[] memory batch2 = new IMulticall.Batch[](2); - batch2[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch2[1] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); + batch2[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch2[1] = IMulticall.Batch( + mockCalleeAddr, + true, + abi.encodeWithSignature("thisMethodReverts()") + ); IMulticall.BatchSelf[] memory batchSelf = new IMulticall.BatchSelf[](2); - batchSelf[0] = IMulticall.BatchSelf(false, abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1)); - batchSelf[1] = - IMulticall.BatchSelf(false, abi.encodeWithSignature("multistaticcall((address,bool,bytes)[])", batch2)); + batchSelf[0] = IMulticall.BatchSelf( + false, + abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1) + ); + batchSelf[1] = IMulticall.BatchSelf( + false, + abi.encodeWithSignature( + "multistaticcall((address,bool,bytes)[])", + batch2 + ) + ); - IMulticall.Result[] memory results = multicall.multicall_self(batchSelf); + IMulticall.Result[] memory results = multicall.multicall_self( + batchSelf + ); assertTrue(results[0].success); assertTrue(results[1].success); assertEq(mockCallee.number(), type(uint256).max); @@ -138,44 +255,92 @@ contract MulticallTest is Test { function testMulticallSelfRevert() public { IMulticall.Batch[] memory batch1 = new IMulticall.Batch[](3); - batch1[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch1[1] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); - batch1[2] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("thisMethodReverts()")); + batch1[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch1[1] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("store(uint256)", type(uint256).max) + ); + batch1[2] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("thisMethodReverts()") + ); IMulticall.Batch[] memory batch2 = new IMulticall.Batch[](2); - batch2[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch2[1] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); + batch2[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch2[1] = IMulticall.Batch( + mockCalleeAddr, + true, + abi.encodeWithSignature("thisMethodReverts()") + ); IMulticall.BatchSelf[] memory batchSelf = new IMulticall.BatchSelf[](2); - batchSelf[0] = IMulticall.BatchSelf(false, abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1)); - batchSelf[1] = - IMulticall.BatchSelf(false, abi.encodeWithSignature("multistaticcall((address,bool,bytes)[])", batch2)); + batchSelf[0] = IMulticall.BatchSelf( + false, + abi.encodeWithSignature("multicall((address,bool,bytes)[])", batch1) + ); + batchSelf[1] = IMulticall.BatchSelf( + false, + abi.encodeWithSignature( + "multistaticcall((address,bool,bytes)[])", + batch2 + ) + ); - vm.expectRevert(abi.encodeWithSelector(Reverted.selector, mockCalleeAddr)); + vm.expectRevert( + abi.encodeWithSelector(Reverted.selector, mockCalleeAddr) + ); multicall.multicall_self(batchSelf); } function testMultistaticcallSuccess() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](2); - batch[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch[1] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); + batch[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch[1] = IMulticall.Batch( + mockCalleeAddr, + true, + abi.encodeWithSignature("thisMethodReverts()") + ); IMulticall.Result[] memory results = multicall.multistaticcall(batch); assertTrue(results[0].success); - assertEq(keccak256(results[0].returnData), keccak256(abi.encodePacked(blockhash(block.number)))); + assertEq( + keccak256(results[0].returnData), + keccak256(abi.encodePacked(blockhash(block.number))) + ); assertTrue(!results[1].success); } function testMultistaticcallRevert() public { IMulticall.Batch[] memory batch = new IMulticall.Batch[](3); - batch[0] = - IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("getBlockHash(uint256)", block.number)); - batch[1] = IMulticall.Batch(mockCalleeAddr, false, abi.encodeWithSignature("store(uint256)", type(uint256).max)); - batch[2] = IMulticall.Batch(mockCalleeAddr, true, abi.encodeWithSignature("thisMethodReverts()")); + batch[0] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("getBlockHash(uint256)", block.number) + ); + batch[1] = IMulticall.Batch( + mockCalleeAddr, + false, + abi.encodeWithSignature("store(uint256)", type(uint256).max) + ); + batch[2] = IMulticall.Batch( + mockCalleeAddr, + true, + abi.encodeWithSignature("thisMethodReverts()") + ); vm.expectRevert(); multicall.multistaticcall(batch); diff --git a/test/utils/SignatureChecker.t.sol b/test/utils/SignatureChecker.t.sol index 9ddc56ed..2f4bc67b 100644 --- a/test/utils/SignatureChecker.t.sol +++ b/test/utils/SignatureChecker.t.sol @@ -21,7 +21,9 @@ contract SignatureCheckerTest is Test { address private maliciousAddr = address(malicious); function setUp() public { - signatureChecker = ISignatureChecker(vyperDeployer.deployContract("src/utils/", "SignatureChecker")); + signatureChecker = ISignatureChecker( + vyperDeployer.deployContract("src/utils/", "SignatureChecker") + ); } function testEOAWithValidSignature() public { @@ -29,8 +31,16 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(signatureChecker.is_valid_signature_now(alice, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); + assertTrue( + signatureChecker.is_valid_signature_now(alice, hash, signature) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signature + ) + ); } function testEOAWithInvalidSigner() public { @@ -38,8 +48,16 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key + 1, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now(alice, hash, signature) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signature + ) + ); } function testEOAWithInvalidSignature1() public { @@ -48,8 +66,20 @@ contract SignatureCheckerTest is Test { bytes32 hashWrong = keccak256("WAGMI1"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hashWrong); bytes memory signatureInvalid = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signatureInvalid)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signatureInvalid)); + assertTrue( + !signatureChecker.is_valid_signature_now( + alice, + hash, + signatureInvalid + ) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signatureInvalid + ) + ); } function testEOAWithInvalidSignature2() public { @@ -59,18 +89,35 @@ contract SignatureCheckerTest is Test { bytes memory signatureInvalid = abi.encodePacked(r, s, bytes1(0xa0)); vm.expectRevert(bytes("ECDSA: invalid signature")); signatureChecker.is_valid_signature_now(alice, hash, signatureInvalid); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signatureInvalid)); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signatureInvalid + ) + ); } function testEOAWithTooHighSValue() public { (address alice, uint256 key) = makeAddrAndKey("alice"); bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); - uint256 sTooHigh = uint256(s) + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; - bytes memory signatureInvalid = abi.encodePacked(r, bytes32(sTooHigh), v); + uint256 sTooHigh = uint256(s) + + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; + bytes memory signatureInvalid = abi.encodePacked( + r, + bytes32(sTooHigh), + v + ); vm.expectRevert(bytes("ECDSA: invalid signature `s` value")); signatureChecker.is_valid_signature_now(alice, hash, signatureInvalid); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signatureInvalid)); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signatureInvalid + ) + ); } function testEIP1271WithValidSignature() public { @@ -78,8 +125,16 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); - assertTrue(signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); + assertTrue( + signatureChecker.is_valid_signature_now(walletAddr, hash, signature) + ); + assertTrue( + signatureChecker.is_valid_ERC1271_signature_now( + walletAddr, + hash, + signature + ) + ); } function testEIP1271WithInvalidSigner() public { @@ -87,8 +142,20 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key + 1, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now( + walletAddr, + hash, + signature + ) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + walletAddr, + hash, + signature + ) + ); } function testEIP1271WithInvalidSignature1() public { @@ -97,8 +164,20 @@ contract SignatureCheckerTest is Test { bytes32 hashWrong = keccak256("WAGMI1"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hashWrong); bytes memory signatureInvalid = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signatureInvalid)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signatureInvalid)); + assertTrue( + !signatureChecker.is_valid_signature_now( + walletAddr, + hash, + signatureInvalid + ) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + walletAddr, + hash, + signatureInvalid + ) + ); } function testEIP1271WithInvalidSignature2() public { @@ -107,8 +186,18 @@ contract SignatureCheckerTest is Test { (, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signatureInvalid = abi.encodePacked(r, s, bytes1(0xa0)); vm.expectRevert(bytes("ECDSA: invalid signature")); - signatureChecker.is_valid_signature_now(walletAddr, hash, signatureInvalid); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signatureInvalid)); + signatureChecker.is_valid_signature_now( + walletAddr, + hash, + signatureInvalid + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + walletAddr, + hash, + signatureInvalid + ) + ); } function testEIP1271WithMaliciousWallet() public { @@ -116,8 +205,20 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(maliciousAddr, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(maliciousAddr, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now( + maliciousAddr, + hash, + signature + ) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + maliciousAddr, + hash, + signature + ) + ); } function testEIP1271NoIsValidSignatureFunction() public { @@ -125,34 +226,75 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256("WAGMI"); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(deployer, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(deployer, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now(deployer, hash, signature) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + deployer, + hash, + signature + ) + ); } - function testFuzzEOAWithValidSignature(string calldata signer, string calldata message) public { + function testFuzzEOAWithValidSignature( + string calldata signer, + string calldata message + ) public { (address alice, uint256 key) = makeAddrAndKey(signer); bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(signatureChecker.is_valid_signature_now(alice, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); + assertTrue( + signatureChecker.is_valid_signature_now(alice, hash, signature) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signature + ) + ); } - function testFuzzEOAWithInvalidSigner(string calldata signer, string calldata message) public { + function testFuzzEOAWithInvalidSigner( + string calldata signer, + string calldata message + ) public { (address alice, uint256 key) = makeAddrAndKey(signer); bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key + 1, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now(alice, hash, signature) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signature + ) + ); } - function testFuzzEOAWithInvalidSignature(bytes calldata signature, string calldata message) public { + function testFuzzEOAWithInvalidSignature( + bytes calldata signature, + string calldata message + ) public { vm.assume(signature.length < 64); address alice = makeAddr("alice"); bytes32 hash = keccak256(abi.encode(message)); - assertTrue(!signatureChecker.is_valid_signature_now(alice, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(alice, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now(alice, hash, signature) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + alice, + hash, + signature + ) + ); } function testFuzzEIP1271WithValidSignature(string calldata message) public { @@ -160,24 +302,64 @@ contract SignatureCheckerTest is Test { bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); - assertTrue(signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); + assertTrue( + signatureChecker.is_valid_signature_now(walletAddr, hash, signature) + ); + assertTrue( + signatureChecker.is_valid_ERC1271_signature_now( + walletAddr, + hash, + signature + ) + ); } - function testFuzzEIP1271WithInvalidSigner(string calldata signer, string calldata message) public { - vm.assume(keccak256(abi.encode(signer)) != keccak256(abi.encode("alice"))); + function testFuzzEIP1271WithInvalidSigner( + string calldata signer, + string calldata message + ) public { + vm.assume( + keccak256(abi.encode(signer)) != keccak256(abi.encode("alice")) + ); (, uint256 key) = makeAddrAndKey(signer); bytes32 hash = keccak256(abi.encode(message)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); bytes memory signature = abi.encodePacked(r, s, v); - assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now( + walletAddr, + hash, + signature + ) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + walletAddr, + hash, + signature + ) + ); } - function testEIP1271WithInvalidSignature(bytes calldata signature, string calldata message) public { + function testEIP1271WithInvalidSignature( + bytes calldata signature, + string calldata message + ) public { vm.assume(signature.length < 64); bytes32 hash = keccak256(abi.encode(message)); - assertTrue(!signatureChecker.is_valid_signature_now(walletAddr, hash, signature)); - assertTrue(!signatureChecker.is_valid_ERC1271_signature_now(walletAddr, hash, signature)); + assertTrue( + !signatureChecker.is_valid_signature_now( + walletAddr, + hash, + signature + ) + ); + assertTrue( + !signatureChecker.is_valid_ERC1271_signature_now( + walletAddr, + hash, + signature + ) + ); } } diff --git a/test/utils/interfaces/IBase64.sol b/test/utils/interfaces/IBase64.sol index 1184883d..69f5c047 100644 --- a/test/utils/interfaces/IBase64.sol +++ b/test/utils/interfaces/IBase64.sol @@ -2,7 +2,13 @@ pragma solidity ^0.8.23; interface IBase64 { - function encode(bytes calldata data, bool base64Url) external pure returns (string[] memory); + function encode( + bytes calldata data, + bool base64Url + ) external pure returns (string[] memory); - function decode(string calldata data, bool base64Url) external pure returns (bytes[] memory); + function decode( + string calldata data, + bool base64Url + ) external pure returns (bytes[] memory); } diff --git a/test/utils/interfaces/ICreate2Address.sol b/test/utils/interfaces/ICreate2Address.sol index e12ff008..ad829609 100644 --- a/test/utils/interfaces/ICreate2Address.sol +++ b/test/utils/interfaces/ICreate2Address.sol @@ -2,7 +2,14 @@ pragma solidity ^0.8.23; interface ICreate2Address { - function compute_address_self(bytes32 salt, bytes32 bytecodeHash) external view returns (address); + function compute_address_self( + bytes32 salt, + bytes32 bytecodeHash + ) external view returns (address); - function compute_address(bytes32 salt, bytes32 bytecodeHash, address deployer) external view returns (address); + function compute_address( + bytes32 salt, + bytes32 bytecodeHash, + address deployer + ) external view returns (address); } diff --git a/test/utils/interfaces/ICreateAddress.sol b/test/utils/interfaces/ICreateAddress.sol index 95303897..dd002989 100644 --- a/test/utils/interfaces/ICreateAddress.sol +++ b/test/utils/interfaces/ICreateAddress.sol @@ -2,7 +2,12 @@ pragma solidity ^0.8.23; interface ICreateAddress { - function compute_address_rlp_self(uint256 nonce) external view returns (address); + function compute_address_rlp_self( + uint256 nonce + ) external view returns (address); - function compute_address_rlp(address deployer, uint256 nonce) external view returns (address); + function compute_address_rlp( + address deployer, + uint256 nonce + ) external view returns (address); } diff --git a/test/utils/interfaces/IECDSA.sol b/test/utils/interfaces/IECDSA.sol index 062209b2..b6588e43 100644 --- a/test/utils/interfaces/IECDSA.sol +++ b/test/utils/interfaces/IECDSA.sol @@ -2,16 +2,26 @@ pragma solidity ^0.8.23; interface IECDSA { - function recover_sig(bytes32 hash, bytes calldata signature) external pure returns (address); + function recover_sig( + bytes32 hash, + bytes calldata signature + ) external pure returns (address); - function to_eth_signed_message_hash(bytes32 hash) external pure returns (bytes32); + function to_eth_signed_message_hash( + bytes32 hash + ) external pure returns (bytes32); - function to_typed_data_hash(bytes32 domainSeparator, bytes32 structHash) external pure returns (bytes32); + function to_typed_data_hash( + bytes32 domainSeparator, + bytes32 structHash + ) external pure returns (bytes32); - function to_data_with_intended_validator_hash_self(bytes calldata data) external view returns (bytes32); + function to_data_with_intended_validator_hash_self( + bytes calldata data + ) external view returns (bytes32); - function to_data_with_intended_validator_hash(address validator, bytes calldata data) - external - pure - returns (bytes32); + function to_data_with_intended_validator_hash( + address validator, + bytes calldata data + ) external pure returns (bytes32); } diff --git a/test/utils/interfaces/IEIP712DomainSeparator.sol b/test/utils/interfaces/IEIP712DomainSeparator.sol index 6867b5dc..cf2ffa0b 100644 --- a/test/utils/interfaces/IEIP712DomainSeparator.sol +++ b/test/utils/interfaces/IEIP712DomainSeparator.sol @@ -6,5 +6,7 @@ import {IERC5267} from "openzeppelin/interfaces/IERC5267.sol"; interface IEIP712DomainSeparator is IERC5267 { function domain_separator_v4() external view returns (bytes32); - function hash_typed_data_v4(bytes32 structHash) external view returns (bytes32); + function hash_typed_data_v4( + bytes32 structHash + ) external view returns (bytes32); } diff --git a/test/utils/interfaces/IMath.sol b/test/utils/interfaces/IMath.sol index 0b7c7123..41a33c8c 100644 --- a/test/utils/interfaces/IMath.sol +++ b/test/utils/interfaces/IMath.sol @@ -2,7 +2,10 @@ pragma solidity ^0.8.23; interface IMath { - function uint256_average(uint256 x, uint256 y) external pure returns (uint256); + function uint256_average( + uint256 x, + uint256 y + ) external pure returns (uint256); function int256_average(int256 x, int256 y) external pure returns (int256); @@ -10,7 +13,12 @@ interface IMath { function signum(int256 x) external pure returns (int256); - function mul_div(uint256 x, uint256 y, uint256 denominator, bool roundup) external pure returns (uint256); + function mul_div( + uint256 x, + uint256 y, + uint256 denominator, + bool roundup + ) external pure returns (uint256); function log_2(uint256 x, bool roundup) external pure returns (uint256); diff --git a/test/utils/interfaces/IMerkleProofVerification.sol b/test/utils/interfaces/IMerkleProofVerification.sol index 2f57fd8b..b740cbbe 100644 --- a/test/utils/interfaces/IMerkleProofVerification.sol +++ b/test/utils/interfaces/IMerkleProofVerification.sol @@ -2,7 +2,11 @@ pragma solidity ^0.8.23; interface IMerkleProofVerification { - function verify(bytes32[] calldata proof, bytes32 root, bytes32 leaf) external pure returns (bool); + function verify( + bytes32[] calldata proof, + bytes32 root, + bytes32 leaf + ) external pure returns (bool); function multi_proof_verify( bytes32[] calldata proof, diff --git a/test/utils/interfaces/IMulticall.sol b/test/utils/interfaces/IMulticall.sol index eb896cd3..4afa886b 100644 --- a/test/utils/interfaces/IMulticall.sol +++ b/test/utils/interfaces/IMulticall.sol @@ -25,11 +25,19 @@ interface IMulticall { bytes returnData; } - function multicall(Batch[] calldata batch) external returns (Result[] memory results); + function multicall( + Batch[] calldata batch + ) external returns (Result[] memory results); - function multicall_value(BatchValue[] calldata batchValue) external payable returns (Result[] memory results); + function multicall_value( + BatchValue[] calldata batchValue + ) external payable returns (Result[] memory results); - function multicall_self(BatchSelf[] calldata batchSelf) external returns (Result[] memory results); + function multicall_self( + BatchSelf[] calldata batchSelf + ) external returns (Result[] memory results); - function multistaticcall(Batch[] calldata batch) external pure returns (Result[] memory results); + function multistaticcall( + Batch[] calldata batch + ) external pure returns (Result[] memory results); } diff --git a/test/utils/interfaces/ISignatureChecker.sol b/test/utils/interfaces/ISignatureChecker.sol index 32f32e3d..2386e53d 100644 --- a/test/utils/interfaces/ISignatureChecker.sol +++ b/test/utils/interfaces/ISignatureChecker.sol @@ -2,13 +2,15 @@ pragma solidity ^0.8.23; interface ISignatureChecker { - function is_valid_signature_now(address signer, bytes32 hash, bytes calldata signature) - external - view - returns (bool); + function is_valid_signature_now( + address signer, + bytes32 hash, + bytes calldata signature + ) external view returns (bool); - function is_valid_ERC1271_signature_now(address signer, bytes32 hash, bytes calldata signature) - external - view - returns (bool); + function is_valid_ERC1271_signature_now( + address signer, + bytes32 hash, + bytes calldata signature + ) external view returns (bool); } diff --git a/test/utils/mocks/Create2Impl.sol b/test/utils/mocks/Create2Impl.sol index cb448f67..3afdd15b 100644 --- a/test/utils/mocks/Create2Impl.sol +++ b/test/utils/mocks/Create2Impl.sol @@ -30,7 +30,10 @@ contract Create2Impl { * @param codeHash The 32-byte bytecode digest of the contract creation bytecode. * @return address The 20-byte address where a contract will be stored. */ - function computeAddress(bytes32 salt, bytes32 codeHash) public view returns (address) { + function computeAddress( + bytes32 salt, + bytes32 codeHash + ) public view returns (address) { return Create2.computeAddress(salt, codeHash); } @@ -43,11 +46,11 @@ contract Create2Impl { * @param deployer The 20-byte deployer address. * @return address The 20-byte address where a contract will be stored. */ - function computeAddressWithDeployer(bytes32 salt, bytes32 codeHash, address deployer) - public - pure - returns (address) - { + function computeAddressWithDeployer( + bytes32 salt, + bytes32 codeHash, + address deployer + ) public pure returns (address) { return Create2.computeAddress(salt, codeHash, deployer); } diff --git a/test/utils/mocks/ERC1271MaliciousMock.sol b/test/utils/mocks/ERC1271MaliciousMock.sol index 3c3aebd7..c4a39baf 100644 --- a/test/utils/mocks/ERC1271MaliciousMock.sol +++ b/test/utils/mocks/ERC1271MaliciousMock.sol @@ -15,10 +15,16 @@ contract ERC1271MaliciousMock is IERC1271 { * @dev Returns a malicious 4-byte magic value. * @return bytes4 The malicious 4-byte magic value. */ - function isValidSignature(bytes32, bytes memory) public pure override returns (bytes4) { + function isValidSignature( + bytes32, + bytes memory + ) public pure override returns (bytes4) { // solhint-disable-next-line no-inline-assembly assembly { - mstore(0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + mstore( + 0, + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + ) return(0, 32) } } diff --git a/test/utils/mocks/ERC1271WalletMock.sol b/test/utils/mocks/ERC1271WalletMock.sol index a3d5d118..433c8d2c 100644 --- a/test/utils/mocks/ERC1271WalletMock.sol +++ b/test/utils/mocks/ERC1271WalletMock.sol @@ -21,7 +21,13 @@ contract ERC1271WalletMock is Ownable, IERC1271 { * @param signature The secp256k1 64/65-byte signature of `hash`. * @return bytes4 The 4-byte magic value. */ - function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4) { - return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0); + function isValidSignature( + bytes32 hash, + bytes memory signature + ) public view override returns (bytes4) { + return + ECDSA.recover(hash, signature) == owner() + ? this.isValidSignature.selector + : bytes4(0); } } diff --git a/test/utils/mocks/ERC20Mock.sol b/test/utils/mocks/ERC20Mock.sol index 41384ef2..b7d91b4f 100644 --- a/test/utils/mocks/ERC20Mock.sol +++ b/test/utils/mocks/ERC20Mock.sol @@ -11,10 +11,12 @@ import {ERC20} from "openzeppelin/token/ERC20/ERC20.sol"; * @dev Allows to mock a simple ERC-20 implementation. */ contract ERC20Mock is ERC20 { - constructor(string memory name_, string memory symbol_, address initialAccount_, uint256 initialBalance_) - payable - ERC20(name_, symbol_) - { + constructor( + string memory name_, + string memory symbol_, + address initialAccount_, + uint256 initialBalance_ + ) payable ERC20(name_, symbol_) { _mint(initialAccount_, initialBalance_); } diff --git a/test/utils/mocks/MockCallee.sol b/test/utils/mocks/MockCallee.sol index e0bbabbc..129883c7 100644 --- a/test/utils/mocks/MockCallee.sol +++ b/test/utils/mocks/MockCallee.sol @@ -33,7 +33,9 @@ contract MockCallee { * @param blockNumber The block number. * @return blockHash The 32-byte block hash. */ - function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { + function getBlockHash( + uint256 blockNumber + ) public view returns (bytes32 blockHash) { blockHash = blockhash(blockNumber); } @@ -50,7 +52,7 @@ contract MockCallee { */ function transferEther(address target) public payable { // solhint-disable-next-line avoid-low-level-calls - (bool ok,) = target.call{value: msg.value}(""); + (bool ok, ) = target.call{value: msg.value}(""); if (!ok) revert Reverted(self); } } From 28573728b35cd74d0589abe1420476af812e933f Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Thu, 18 Jan 2024 15:58:33 +0100 Subject: [PATCH 13/46] =?UTF-8?q?=F0=9F=90=9B=20Fix=20typos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 6 +++--- test/governance/TimelockController.t.sol | 2 +- test/tokens/mocks/ERC721ReceiverMock.sol | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index fab3acdf..21d0b7b5 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -118,18 +118,18 @@ event RoleRevoked: # @dev Proposer 32-byte role. -# @notice Responsable for proposing operations. +# @notice Responsible for proposing operations. PROPOSER_ROLE: public(constant(bytes32)) = keccak256("PROPOSER_ROLE") # @dev Executor 32-byte role. -# @notice Responsable for executing scheduled +# @notice Responsible for executing scheduled # proposals. EXECUTOR_ROLE: public(constant(bytes32)) = keccak256("EXECUTOR_ROLE") # @dev Canceller 32-byte role. -# @notice Responsable for cancelling proposals. +# @notice Responsible for cancelling proposals. CANCELLER_ROLE: public(constant(bytes32)) = keccak256("CANCELLER_ROLE") diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 85a16bd2..2ae6df4c 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -925,7 +925,7 @@ contract TimelockControllerTest is Test { vm.prank(PROPOSER_ONE); - // Schedule batch executon + // Schedule batch execution timelockController.scheduleBatch( targets, values, diff --git a/test/tokens/mocks/ERC721ReceiverMock.sol b/test/tokens/mocks/ERC721ReceiverMock.sol index c0bcf7e2..03b46c89 100644 --- a/test/tokens/mocks/ERC721ReceiverMock.sol +++ b/test/tokens/mocks/ERC721ReceiverMock.sol @@ -21,7 +21,6 @@ contract ERC721ReceiverMock is IERC721Receiver { Panic } // solhint-disable-next-line var-name-mixedcase - Error private immutable _ERROR; event Received(address operator, address from, uint256 tokenId, bytes data); From 4049a0d37c1d491d6b567245155f5d8143eb7bcf Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Thu, 18 Jan 2024 16:20:40 +0100 Subject: [PATCH 14/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Clarify=20build=20di?= =?UTF-8?q?rectory=20root?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 99eb7496..7a633eeb 100644 --- a/.gitignore +++ b/.gitignore @@ -58,5 +58,5 @@ venv dist *.egg-info -# Vyper build files +# Ape build files .build From 0b776df7441534116348acc52f4ac8b0a985fc21 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Thu, 18 Jan 2024 16:29:44 +0100 Subject: [PATCH 15/46] =?UTF-8?q?=F0=9F=93=96=20Add=20`README`=20and=20`CH?= =?UTF-8?q?ANGELOG`=20Entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- CHANGELOG.md | 5 +++++ README.md | 3 +++ src/governance/TimelockController.vy | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aac8a0d0..8a3b56a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [`0.0.5`](https://github.com/pcaversaccio/snekmate/releases/tag/v0.0.5) (Unreleased) +### 💥 New Features + +- **Extensions** + - [`TimelockController`](https://github.com/pcaversaccio/snekmate/blob/v0.0.5/src/governance/TimelockController.vy): A multi-role-based timelock controller reference implementation. ([#195](https://github.com/pcaversaccio/snekmate/pull/195)) + ### ♻️ Refactoring - **Utility Functions** diff --git a/README.md b/README.md index e0c77f0b..72d02b0b 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ src │ ├── ERC4626 — "Modern and Gas-Efficient ERC-4626 Tokenised Vault Implementation" │ └── interfaces │ └── IERC2981 — "EIP-2981 Interface Definition" +├── governance +│ └── TimelockController — "Multi-Role-Based Timelock Controller Reference Implementation" ├── tokens │ ├── ERC20 — "Modern and Gas-Efficient ERC-20 + EIP-2612 Implementation" │ ├── ERC721 — "Modern and Gas-Efficient ERC-721 + EIP-4494 Implementation" @@ -113,6 +115,7 @@ This repository contains [Foundry](https://github.com/foundry-rs/foundry)-based | `AccessControl` | ✅ | ✅ | ✅ | | `ERC2981` | ✅ | ✅ | ✅ | | `ERC4626` | ✅ | ✅ | ✅ | +| `TimelockController` | ✅ | ✅ | ✅ | | `ERC20` | ✅ | ✅ | ✅ | | `ERC721` | ✅ | ✅ | ✅ | | `ERC1155` | ✅ | ✅ | ✅ | diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 21d0b7b5..4650f4e3 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -1,6 +1,6 @@ # pragma version ^0.3.10 """ -@title Owner-Based Timelock Controller +@title Multi-Role-Based Timelock Controller Reference Implementation @custom:contract-name TimelockController @license GNU Affero General Public License v3.0 only @author cairoeth From 4032693009ee97b43e8206c0190c937e874384b3 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Fri, 19 Jan 2024 17:12:00 +0100 Subject: [PATCH 16/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20First=20Refactori?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 845 +++++++++++++-------------- 1 file changed, 405 insertions(+), 440 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 4650f4e3..960e7961 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -3,7 +3,8 @@ @title Multi-Role-Based Timelock Controller Reference Implementation @custom:contract-name TimelockController @license GNU Affero General Public License v3.0 only -@author cairoeth +@author pcaversaccio +@custom:coauthor cairoeth @notice This module allows for timelocking operations by scheduling and executing transactions. By leveraging AccessControl, the TimelockController introduces three roles: proposer, executor, @@ -13,7 +14,7 @@ proposals. The owner is the sole admin of the roles and can grant and revoke them. In the constructor, proposers will be granted the proposer and canceller roles. - + Proposals must be scheduled with a delay that is greater than or equal to the minimum delay (`minDelay()`), which can be updated via a proposal to itself and is measured in seconds. Additionally, @@ -47,20 +48,19 @@ implements: IAccessControl DEFAULT_ADMIN_ROLE: public(constant(bytes32)) = empty(bytes32) -# @dev An additional 32-byte access role. -# @notice Please adjust the naming of the variable -# according to your specific requirement, -# e.g. `MINTER_ROLE`. -ADDITIONAL_ROLE_1: public(constant(bytes32)) = keccak256("ADDITIONAL_ROLE_1") +# @dev The 32-byte proposer role. +# @notice Responsible for proposing operations. +PROPOSER_ROLE: public(constant(bytes32)) = keccak256("PROPOSER_ROLE") + + +# @dev The 32-byte executor role. +# @notice Responsible for executing scheduled proposals. +EXECUTOR_ROLE: public(constant(bytes32)) = keccak256("EXECUTOR_ROLE") -# @dev An additional 32-byte access role. -# @notice Please adjust the naming of the variable -# according to your specific requirement, -# e.g. `PAUSER_ROLE`. Also, feel free to add more -# roles if necessary. In this case, it is important -# to extend the constructor accordingly. -ADDITIONAL_ROLE_2: public(constant(bytes32)) = keccak256("ADDITIONAL_ROLE_2") +# @dev The 32-byte canceller role. +# @notice Responsible for cancelling proposals. +CANCELLER_ROLE: public(constant(bytes32)) = keccak256("CANCELLER_ROLE") # @dev Stores the ERC-165 interface identifier for each @@ -73,93 +73,52 @@ _SUPPORTED_INTERFACES: constant(bytes4[2]) = [ ] -# @dev Returns `True` if `account` has been granted `role`. -# @notice If you declare a variable as `public`, -# Vyper automatically generates an `external` -# getter function for the variable. -hasRole: public(HashMap[bytes32, HashMap[address, bool]]) - - -# @dev Returns the admin role that controls `role`. -getRoleAdmin: public(HashMap[bytes32, bytes32]) - - -# @dev Emitted when `new_admin_role` is set as -# `role`'s admin role, replacing `previous_admin_role`. -# Note that `DEFAULT_ADMIN_ROLE` is the starting -# admin for all roles, despite `RoleAdminChanged` -# not being emitted signaling this. -event RoleAdminChanged: - role: indexed(bytes32) - previous_admin_role: indexed(bytes32) - new_admin_role: indexed(bytes32) - - -# @dev Emitted when `account` is granted `role`. -# Note that `sender` is the account (an admin -# role bearer) that originated the contract call. -event RoleGranted: - role: indexed(bytes32) - account: indexed(address) - sender: indexed(address) - - -# @dev Emitted when `account` is revoked `role`. -# Note that `sender` is the account that originated -# the contract call: -# - if using `revokeRole`, it is the admin role -# bearer, -# - if using `renounceRole`, it is the role bearer -# (i.e. `account`). -event RoleRevoked: - role: indexed(bytes32) - account: indexed(address) - sender: indexed(address) - - -# @dev Proposer 32-byte role. -# @notice Responsible for proposing operations. -PROPOSER_ROLE: public(constant(bytes32)) = keccak256("PROPOSER_ROLE") - - -# @dev Executor 32-byte role. -# @notice Responsible for executing scheduled -# proposals. -EXECUTOR_ROLE: public(constant(bytes32)) = keccak256("EXECUTOR_ROLE") +# @dev The 32-byte timestamp that specifies whether a +# proposal has been executed. +_DONE_TIMESTAMP: constant(uint256) = 1 -# @dev Canceller 32-byte role. -# @notice Responsible for cancelling proposals. -CANCELLER_ROLE: public(constant(bytes32)) = keccak256("CANCELLER_ROLE") +# @dev The possible states of a proposal. +# @notice Enums are treated differently in Vyper and Solidity. +# The members are represented by `uint256` values (in Solidity +# the values are of type `uint8`) in the form `2**n`, where `n` +# is the index of the member in the range `0 <= n <= 255` (i.e. +# the first index value is 1). For further insights also, see +# the following Twitter thread: +# https://twitter.com/pcaversaccio/status/1626514029094047747. +enum OperationState: + UNSET + WAITING + READY + DONE -# @dev The timestamp that represents that a -# proposal has been executed. -_DONE_TIMESTAMP: constant(uint256) = 1 +# @dev Returns the timestamp at which an operation becomes +# ready (`0` for `UNSET` operations, `1` for `DONE` operations). +get_timestamp: public(HashMap[bytes32, uint256]) -# @dev The mapping of proposal IDs to their -# timestamps. -_timestamps: HashMap[bytes32, uint256] +# @dev Returns the minimum delay in seconds for an operation +# to become valid. This value can be changed by executing an +# operation that invokes `update_delay`. +get_minimum_delay: public(uint256) -# @dev The minimum delay required to schedule a -# proposal. -_minDelay: uint256 +# @dev Returns `True` if `account` has been granted `role`. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. +hasRole: public(HashMap[bytes32, HashMap[address, bool]]) -# @dev The possible statuses of a proposal. -enum OperationState: - Unset - Waiting - Ready - Done +# @dev Returns the admin role that controls `role`. +getRoleAdmin: public(HashMap[bytes32, bytes32]) -# @dev Emitted when a call is scheduled as part -# of operation `id`. Note that the `index` is the -# index position of the proposal. If the proposal -# is individual, the `index` is 0. +# @dev Emitted when a call is scheduled as part of +# operation `id`. Note that `index` is the index +# position of the proposal. If the proposal is +# individual, the `index` is `0`. event CallScheduled: id: indexed(bytes32) index: indexed(uint256) @@ -171,9 +130,9 @@ event CallScheduled: # @dev Emitted when a call is performed as part -# of operation `id`. Note that the `index` is -# the index position of the proposal. If the -# proposal is individual, the `index` is 0. +# of operation `id`. Note that `index` is the +# index position of the proposal. If the proposal +# is individual, the `index` is `0`. event CallExecuted: id: indexed(bytes32) index: indexed(uint256) @@ -182,8 +141,8 @@ event CallExecuted: data: Bytes[1_024] -# @dev Emitted when new proposal is scheduled -# with non-zero salt. +# @dev Emitted when new proposal is scheduled with +# non-zero salt. event CallSalt: id: indexed(bytes32) salt: bytes32 @@ -196,43 +155,94 @@ event Cancelled: # @dev Emitted when the minimum delay for future # operations is modified. -event MinDelayChange: - oldDuration: uint256 - newDuration: uint256 +event MinimumDelayChange: + old_duration: uint256 + new_duration: uint256 + + +# @dev Emitted when `new_admin_role` is set as +# `role`'s admin role, replacing `previous_admin_role`. +# Note that `DEFAULT_ADMIN_ROLE` is the starting +# admin for all roles, despite `RoleAdminChanged` +# not being emitted signaling this. +event RoleAdminChanged: + role: indexed(bytes32) + previous_admin_role: indexed(bytes32) + new_admin_role: indexed(bytes32) + + +# @dev Emitted when `account` is granted `role`. +# Note that `sender` is the account (an admin +# role bearer) that originated the contract call. +event RoleGranted: + role: indexed(bytes32) + account: indexed(address) + sender: indexed(address) + + +# @dev Emitted when `account` is revoked `role`. +# Note that `sender` is the account that originated +# the contract call: +# - if using `revokeRole`, it is the admin role +# bearer, +# - if using `renounceRole`, it is the role bearer +# (i.e. `account`). +event RoleRevoked: + role: indexed(bytes32) + account: indexed(address) + sender: indexed(address) @external -def __init__(minDelay: uint256, proposers: DynArray[address, 128], executors: DynArray[address, 128], admin: address): - """ - @dev The optional admin can aid with initial - configuration of roles after deployment without - being subject to delay, but this role should be - subsequently renounced in favor of - administration through timelocked proposals. - Previous versions of this contract would assign - this admin to the deployer automatically and - should be renounced as well. - @notice Assigns roles to given addresses and sets the - minimum delay. - """ - # Self administration +@payable +def __init__(minimum_delay_: uint256, proposers_: DynArray[address, 128], executors_: DynArray[address, 128], admin_: address): + """ + @dev Initialises the contract with the following parameters: + - `minimum_delay_`: The initial minimum delay in seconds + for operations, + - `proposers_`: The accounts to be granted proposer and + canceller roles, + - `executors_`: The accounts to be granted executor role, + - `admin_`: The optional account to be granted admin role + (disable with the zero address). + + IMPORTANT: The optional admin can aid with initial + configuration of roles after deployment without being + subject to delay, but this role should be subsequently + renounced in favor of administration through timelocked + proposals. + + To omit the opcodes for checking the `msg.value` + in the creation-time EVM bytecode, the constructor + is declared as `payable`. + @param minimum_delay_ The 32-byte minimum delay in seconds + for operations. + @param proposers_ The 20-byte array of accounts to be granted + proposer and canceller roles. + @param executors_ The 20-byte array of accounts to be granted + executor role. + @param admin_ The 20-byte (optional) account to be granted admin + role. + """ + # Configure the contract to be self-administered. self._grant_role(DEFAULT_ADMIN_ROLE, self) - # Optional admin - if (admin != empty(address)): - self._grant_role(DEFAULT_ADMIN_ROLE, admin) + # Set the optional admin. + if (admin_ != empty(address)): + self._grant_role(DEFAULT_ADMIN_ROLE, admin_) - # Register proposers and cancellers - for proposer in proposers: + # Register the proposers and cancellers. + for proposer in proposers_: self._grant_role(PROPOSER_ROLE, proposer) self._grant_role(CANCELLER_ROLE, proposer) - # Register executors - for executor in executors: + # Register the executors. + for executor in executors_: self._grant_role(EXECUTOR_ROLE, executor) - self._minDelay = minDelay - log MinDelayChange(0, minDelay) + # Set the minimum delay. + self.get_minimum_delay = minimum_delay_ + log MinimumDelayChange(empty(uint256), minimum_delay_) @external @@ -245,20 +255,6 @@ def __default__(): pass -@internal -def _onlyRoleOrOpenRole(role: bytes32): - """ - @dev Used to limit a function to be callable only by - a certain role. In addition to checking the - sender's role, `empty(address)` is also - considered. Granting a role to `empty(address)` - is equivalent to enabling this role for everyone. - @param role The 32-byte role definition. - """ - if (not(self.hasRole[role][empty(address)])): - self._check_role(role, msg.sender) - - @external @view def supportsInterface(interface_id: bytes4) -> bool: @@ -274,33 +270,21 @@ def supportsInterface(interface_id: bytes4) -> bool: @external @view -def isOperation(id: bytes32) -> bool: +def is_operation(id: bytes32) -> bool: """ - @dev Returns whether an id corresponds to a registered - operation. This includes both Waiting, Ready, and - Done operations. + @dev Returns whether an `id` corresponds to a registered + operation. This includes both `WAITING`, `READY`, and + `DONE` operations. @param id The 32-byte operation identifier. - @return bool The verification whether the id - corresponds to a registered operation or not. - """ - return self._isOperation(id) - - -@internal -@view -def _isOperation(id: bytes32) -> bool: - """ - @dev Internal logic of `isOperation`. - @param id The 32-byte operation identifier. - @return bool The verification whether the id + @return bool The verification whether the `id` corresponds to a registered operation or not. """ - return self._getOperationState(id) != OperationState.Unset + return self._is_operation(id) @external @view -def isOperationPending(id: bytes32) -> bool: +def is_operation_pending(id: bytes32) -> bool: """ @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be @@ -309,254 +293,119 @@ def isOperationPending(id: bytes32) -> bool: @return bool The verification whether the operation is pending or not. """ - return self._isOperationPending(id) - - -@internal -@view -def _isOperationPending(id: bytes32) -> bool: - """ - @dev Internal logic of `isOperationPending`. - @param id The 32-byte operation identifier. - @return bool The verification whether the operation - is pending or not. - """ - state: OperationState = self._getOperationState(id) - return state == OperationState.Waiting or state == OperationState.Ready + return self._is_operation_pending(id) @external @view -def isOperationReady(id: bytes32) -> bool: - """ - @dev Returns whether an operation is ready - for execution. Note that a "ready" - operation is also "pending". - @param id The 32-byte operation identifier. - @return bool The verification whether - the operation is ready or not. - """ - return self._isOperationReady(id) - - -@internal -@view -def _isOperationReady(id: bytes32) -> bool: +def is_operation_ready(id: bytes32) -> bool: """ - @dev Internal logic of `_isOperationReady`. + @dev Returns whether an operation is ready for + execution. Note that a "ready" operation is + also "pending". @param id The 32-byte operation identifier. - @return bool The verification whether - the operation is ready or not. - """ - return self._getOperationState(id) == OperationState.Ready - - -@external -@view -def isOperationDone(id: bytes32) -> bool: - """ - @dev Returns whether an operation is done - or not. - @param id The 32-byte operation identifier. - @return bool The verification whether - the operation is done or not. - """ - return self._isOperationDone(id) - - -@internal -@view -def _isOperationDone(id: bytes32) -> bool: - """ - @dev Internal logic of `_isOperationDone`. - @param id The 32-byte operation identifier. - @return bool The verification whether - the operation is done or not. + @return bool The verification whether the operation + is ready or not. """ - return self._getOperationState(id) == OperationState.Done + return self._is_operation_ready(id) @external @view -def getTimestamp(id: bytes32) -> uint256: +def is_operation_done(id: bytes32) -> bool: """ - @dev Returns the timestamp at which an - operation becomes ready (0 for - unset operations, 1 for done - operations). + @dev Returns whether an operation is done or not. @param id The 32-byte operation identifier. - @return uint256 The timestamp at which - the operation becomes ready. - """ - return self._getTimestamp(id) - - -@internal -@view -def _getTimestamp(id: bytes32) -> uint256: - """ - @dev Internal logic of `_getTimestamp`. - @param id The 32-byte operation identifier. - @return uint256 The timestamp at which - the operation becomes ready. + @return bool The verification whether the operation + is done or not. """ - return self._timestamps[id] + return self._is_operation_done(id) @external @view -def getOperationState(id: bytes32) -> OperationState: +def get_operation_state(id: bytes32) -> OperationState: """ @dev Returns the state of an operation. @param id The 32-byte operation identifier. - @return OperationState The state of the - operation. - """ - return self._getOperationState(id) - - -@internal -@view -def _getOperationState(id: bytes32) -> OperationState: - """ - @dev Internal logic of `_getOperationState`. - @param id The 32-byte operation identifier. - @return OperationState The state of the + @return OperationState The 32-byte state of the operation. """ - timestamp: uint256 = self._getTimestamp(id) - if (timestamp == 0): - return OperationState.Unset - elif (timestamp == _DONE_TIMESTAMP): - return OperationState.Done - elif (timestamp > block.timestamp): - return OperationState.Waiting - else: - return OperationState.Ready - - -@external -@view -def getMinDelay() -> uint256: - """ - @dev Returns the minimum delay in seconds - for an operation to become valid. - This value can be changed by executing - an operation that calls `updateDelay`. - @return uint256 The minimum delay required - to schedule a proposal. - """ - return self._minDelay + return self._get_operation_state(id) @external @pure -def hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: - """ - @dev Returns the identifier of an operation - containing a single transaction. - @param target The address of the target contract. - @param x The amount of native token to send - with the call. - @param data The ABI-encoded call data. - @param predecessor The hash of the preceding - operation (optional with empty bytes). - @param salt The salt of the operation. - @return bytes32 The hash of the operation. - """ - return self._hashOperation(target, x, data, predecessor, salt) - - -@internal -@pure -def _hashOperation(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: +def hash_operation(target: address, amount: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: """ - @dev Internal logic of `hashOperation`. - @param target The address of the target contract. - @param x The amount of native token to send + @dev Returns the identifier of an operation containing + a single transaction. + @param target The 20-bytes address of the target contract. + @param amount The 32-byte amount of native token to transfer with the call. - @param data The ABI-encoded call data. - @param predecessor The hash of the preceding + @param data The maximum 1,024-byte ABI-encoded calldata. + @param predecessor The 32-byte hash of the preceding operation (optional with empty bytes). - @param salt The salt of the operation. - @return bytes32 The hash of the operation. + @param salt The 32-byte salt of the operation. + @return bytes32 The 32-byte hash of the operation. """ - value: uint256 = x - return keccak256(_abi_encode(target, value, data, predecessor, salt)) + return self._hash_operation(target, amount, data, predecessor, salt) @external @pure -def hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: - """ - @dev Returns the identifier of an operation - containing a batch of transactions. - @param targets The address of the targets contract. - @param values The amounts of native token to send - with each call. - @param payloads The ABI-encoded calls data. - @param predecessor The hash of the preceding +def hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ + predecessor: bytes32, salt: bytes32) -> bytes32: + """ + @dev Returns the identifier of an operation containing + a batch of transactions. + @param targets The 20-byte address of the targets contract. + @param amounts The 32-byte array of native token amounts to + transfer with each call. + @param data The maximum 1,024-byte array of ABI-encoded calldata. + @param predecessor The 32-byte hash of the preceding operation (optional with empty bytes). - @param salt The salt of the operation. - @return bytes32 The hash of the operation. + @param salt The 32-byte salt of the operation. + @return bytes32 The 32-byte hash of the operation. """ - return self._hashOperationBatch(targets, values, payloads, predecessor, salt) - - -@internal -@pure -def _hashOperationBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32) -> bytes32: - """ - @dev Internal logic of `hashOperationBatch`. - @param targets The address of the targets contract. - @param values The amounts of native token to send - with each call. - @param payloads The ABI-encoded calls data. - @param predecessor The hash of the preceding - operation (optional with empty bytes). - @param salt The salt of the operation. - @return bytes32 The hash of the operation. - """ - return keccak256(_abi_encode(targets, values, payloads, predecessor, salt)) + return self._hash_operation_batch(targets, amounts, payloads, predecessor, salt) @external -def schedule(target: address, x: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32, delay: uint256): +def schedule(target: address, amount: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32, delay: uint256): """ - @dev Schedule an operation containing a single - transaction. Emits `CallSalt` if salt is - nonzero, and `CallScheduled`. - @param target The address of the target contract. - @param x The amount of native token to send + @dev Schedule an operation containing a single transaction. + Emits `CallSalt` if salt is non-zero and `CallScheduled`. + @notice Requires the caller to have the `proposer` role. + @param target The 20-byte address of the target contract. + @param amount The 32-byte amount of native token to transfer with the call. - @param data The ABI-encoded call data. + @param data The maximum 1,024-byte ABI-encoded calldata. @param predecessor The hash of the preceding operation. @param salt The salt of the operation. @param delay The delay before the operation becomes valid. Must be greater than or equal to the minimum delay. - @notice Requires the caller to have the - `proposer` role. """ self._check_role(PROPOSER_ROLE, msg.sender) - value: uint256 = x - id: bytes32 = self._hashOperation(target, value, data, predecessor, salt) + id: bytes32 = self._hash_operation(target, amount, data, predecessor, salt) self._schedule(id, delay) - log CallScheduled(id, 0, target, value, data, predecessor, delay) + log CallScheduled(id, empty(uint256), target, amount, data, predecessor, delay) if (salt != empty(bytes32)): log CallSalt(id, salt) @external -def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32, delay: uint256): +def schedule_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ + predecessor: bytes32, salt: bytes32, delay: uint256): """ @dev Schedule an operation containing a batch of transactions. Emits `CallSalt` if salt - is nonzero, and one `CallScheduled` event + is non-zero, and one `CallScheduled` event per transaction in the batch. @param targets The address of the target contracts. - @param values The amounts of native token to send + @param amounts The amounts of native token to send with the call. @param payloads The ABI-encoded calls data. @param predecessor The hash of the preceding @@ -569,12 +418,12 @@ def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128 `proposer` role. """ self._check_role(PROPOSER_ROLE, msg.sender) - assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" - id: bytes32 = self._hashOperationBatch(targets, values, payloads, predecessor, salt) + assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: invalid operation length" + id: bytes32 = self._hash_operation_batch(targets, amounts, payloads, predecessor, salt) self._schedule(id, delay) idx: uint256 = empty(uint256) for target in targets: - log CallScheduled(id, idx, target, values[idx], payloads[idx], predecessor, delay) + log CallScheduled(id, idx, target, amounts[idx], payloads[idx], predecessor, delay) # The following line cannot overflow because we have # limited the dynamic array. idx = unsafe_add(idx, 1) @@ -582,21 +431,6 @@ def scheduleBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128 log CallSalt(id, salt) -@internal -def _schedule(id: bytes32, delay: uint256): - """ - @dev Schedule an operation that is to become - valid after a given delay. - @param id The 32-byte operation identifier. - @param delay The delay before the operation - becomes valid. Must be greater than or - equal to the minimum delay. - """ - assert not(self._isOperation(id)), "TimelockController: operation already scheduled" - assert delay >= self._minDelay, "TimelockController: insufficient delay" - self._timestamps[id] = block.timestamp + delay - - @external def cancel(id: bytes32): """ @@ -606,19 +440,20 @@ def cancel(id: bytes32): @param id The 32-byte operation identifier. """ self._check_role(CANCELLER_ROLE, msg.sender) - assert self._isOperationPending(id), "TimelockController: operation cannot be cancelled" - self._timestamps[id] = 0 + assert self._is_operation_pending(id), "TimelockController: operation cannot be cancelled" + self.get_timestamp[id] = empty(uint256) log Cancelled(id) @external -def execute(target: address, x: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32): +@payable +def execute(target: address, amount: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32): """ @dev Execute an (ready) operation containing a single transaction. Emits a `CallExecuted` event. @param target The address of the target contract. - @param x The amount of native token to send + @param amount The amount of native token to send with the call. @param payload The ABI-encoded call data. @param predecessor The hash of the preceding @@ -630,25 +465,26 @@ def execute(target: address, x: uint256, payload: Bytes[1_024], predecessor: byt proposal is pending, thus any modifications to the operation during reentrancy should be caught. """ - self._onlyRoleOrOpenRole(EXECUTOR_ROLE) - value: uint256 = x - id: bytes32 = self._hashOperation(target, value, payload, predecessor, salt) + self._only_role_or_open_role(EXECUTOR_ROLE) + id: bytes32 = self._hash_operation(target, amount, payload, predecessor, salt) - self._beforeCall(id, predecessor) - self._execute(target, value, payload) - log CallExecuted(id, 0, target, value, payload) - self._afterCall(id) + self._before_call(id, predecessor) + self._execute(target, amount, payload) + log CallExecuted(id, empty(uint256), target, amount, payload) + self._after_call(id) @external -def executeBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, salt: bytes32): +@payable +def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ + predecessor: bytes32, salt: bytes32): """ @dev Execute an (ready) operation containing a batch of transactions. Emits one `CallExecuted` event per transaction in the batch. @param targets The address of the target contracts. - @param values The amounts of native token to send + @param amounts The amounts of native token to send with the call. @param payloads The ABI-encoded calls data. @param predecessor The hash of the preceding @@ -660,62 +496,23 @@ def executeBatch(targets: DynArray[address, 128], values: DynArray[uint256, 128] proposal is pending, thus any modifications to the operation during reentrancy should be caught. """ - self._onlyRoleOrOpenRole(EXECUTOR_ROLE) - assert len(targets) == len(values) and len(targets) == len(payloads), "TimelockController: invalid operation length" - id: bytes32 = self._hashOperationBatch(targets, values, payloads, predecessor, salt) + self._only_role_or_open_role(EXECUTOR_ROLE) + assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: invalid operation length" + id: bytes32 = self._hash_operation_batch(targets, amounts, payloads, predecessor, salt) - self._beforeCall(id, predecessor) + self._before_call(id, predecessor) idx: uint256 = empty(uint256) for target in targets: - self._execute(target, values[idx], payloads[idx]) - log CallExecuted(id, idx, target, values[idx], payloads[idx]) + self._execute(target, amounts[idx], payloads[idx]) + log CallExecuted(id, idx, target, amounts[idx], payloads[idx]) # The following line cannot overflow because we have # limited the dynamic array. idx = unsafe_add(idx, 1) - self._afterCall(id) - - -@internal -def _execute(target: address, x: uint256, payload: Bytes[1_024]): - """ - @dev Execute an operation's call. - @param target The address of the target contract. - @param x The amount of native token to send - with the call. - @param payload The ABI-encoded call data. - """ - value: uint256 = x - return_data: Bytes[max_value(uint8)] = b"" - success: bool = empty(bool) - success, return_data = raw_call(target, payload, max_outsize=255, revert_on_failure=False) - assert success, "TimelockController: underlying transaction reverted" - - -@internal -@view -def _beforeCall(id: bytes32, predecessor: bytes32): - """ - @dev Checks before execution of an operation's calls. - @param id The 32-byte operation identifier. - @param predecessor The hash of the preceding - operation. - """ - assert self._isOperationReady(id), "TimelockController: operation is not ready" - assert predecessor == empty(bytes32) or self._isOperationDone(predecessor), "TimelockController: predecessor operation is not done" - - -@internal -def _afterCall(id: bytes32): - """ - @dev Checks after execution of an operation's calls. - @param id The 32-byte operation identifier. - """ - assert self._isOperationReady(id), "TimelockController: operation is not ready" - self._timestamps[id] = _DONE_TIMESTAMP + self._after_call(id) @external -def updateDelay(newDelay: uint256): +def update_delay(new_delay: uint256): """ @dev Changes the minimum timelock duration for future operations. Emits a `MinDelayChange` event. @@ -726,9 +523,9 @@ def updateDelay(newDelay: uint256): is the target and the data is the ABI-encoded call to this function. """ - assert msg.sender == self, "TimelockController: unauthorized" - log MinDelayChange(self._minDelay, newDelay) - self._minDelay = newDelay + assert msg.sender == self, "TimelockController: unauthorised" + log MinimumDelayChange(self.get_minimum_delay, new_delay) + self.get_minimum_delay = new_delay @external @@ -793,12 +590,186 @@ def set_role_admin(role: bytes32, admin_role: bytes32): @internal -def _check_role(role: bytes32, account: address): +@view +def _is_operation(id: bytes32) -> bool: """ - @dev Reverts with a standard message if `account` - is missing `role`. + @dev Internal logic of `isOperation`. + @param id The 32-byte operation identifier. + @return bool The verification whether the id + corresponds to a registered operation or not. + """ + return self._get_operation_state(id) != OperationState.UNSET + + +@internal +def _only_role_or_open_role(role: bytes32): + """ + @dev Used to limit a function to be callable only by + a certain role. In addition to checking the + sender's role, `empty(address)` is also + considered. Granting a role to `empty(address)` + is equivalent to enabling this role for everyone. @param role The 32-byte role definition. - @param account The 20-byte address of the account. + """ + if (not(self.hasRole[role][empty(address)])): + self._check_role(role, msg.sender) + + +@internal +@view +def _is_operation_pending(id: bytes32) -> bool: + """ + @dev Internal logic of `isOperationPending`. + @param id The 32-byte operation identifier. + @return bool The verification whether the operation + is pending or not. + """ + state: OperationState = self._get_operation_state(id) + return state == OperationState.WAITING or state == OperationState.READY + + +@internal +@view +def _is_operation_ready(id: bytes32) -> bool: + """ + @dev Internal logic of `_isOperationReady`. + @param id The 32-byte operation identifier. + @return bool The verification whether + the operation is ready or not. + """ + return self._get_operation_state(id) == OperationState.READY + + +@internal +@view +def _is_operation_done(id: bytes32) -> bool: + """ + @dev Internal logic of `_isOperationDone`. + @param id The 32-byte operation identifier. + @return bool The verification whether + the operation is done or not. + """ + return self._get_operation_state(id) == OperationState.DONE + + +@internal +@view +def _get_operation_state(id: bytes32) -> OperationState: + """ + @dev Internal logic of `_getOperationState`. + @param id The 32-byte operation identifier. + @return OperationState The state of the + operation. + """ + timestamp: uint256 = self.get_timestamp[id] + if (timestamp == empty(uint256)): + return OperationState.UNSET + elif (timestamp == _DONE_TIMESTAMP): + return OperationState.DONE + elif (timestamp > block.timestamp): + return OperationState.WAITING + else: + return OperationState.READY + + +@internal +@pure +def _hash_operation(target: address, amount: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: + """ + @dev Internal logic of `hashOperation`. + @param target The address of the target contract. + @param amount The amount of native token to send + with the call. + @param data The ABI-encoded call data. + @param predecessor The hash of the preceding + operation (optional with empty bytes). + @param salt The salt of the operation. + @return bytes32 The hash of the operation. + """ + return keccak256(_abi_encode(target, amount, data, predecessor, salt)) + + +@internal +@pure +def _hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ + predecessor: bytes32, salt: bytes32) -> bytes32: + """ + @dev An `internal` helper function that returns `hash_operationBatch`. + @param targets The address of the targets contract. + @param amounts The amounts of native token to send + with each call. + @param payloads The ABI-encoded calls data. + @param predecessor The hash of the preceding + operation (optional with empty bytes). + @param salt The salt of the operation. + @return bytes32 The hash of the operation. + """ + return keccak256(_abi_encode(targets, amounts, payloads, predecessor, salt)) + + +@internal +def _schedule(id: bytes32, delay: uint256): + """ + @dev Schedules an operation that is to become valid + after a given delay. + @param id The 32-byte operation identifier. + @param delay The 32-byte delay before the operation + becomes valid. Must be greater than or equal + to the minimum delay. + """ + assert not(self._is_operation(id)), "TimelockController: operation already scheduled" + assert delay >= self.get_minimum_delay, "TimelockController: insufficient delay" + self.get_timestamp[id] = block.timestamp + delay + + +@internal +def _execute(target: address, amount: uint256, payload: Bytes[1_024]): + """ + @dev Executes an operation's call. + @param target The 20-byte address of the target contract. + @param amount The 32-byte amount of native token to transfer + with the call. + @param data The maximum 1,024-byte array of ABI-encoded calldata. + """ + return_data: Bytes[max_value(uint8)] = b"" + success: bool = empty(bool) + success, return_data = raw_call(target, payload, max_outsize=255, value=amount, revert_on_failure=False) + if (not(success)): + if len(return_data) != 0: + raw_revert(return_data) + else: + raise "TimelockController: underlying transaction reverted" + + +@internal +@view +def _before_call(id: bytes32, predecessor: bytes32): + """ + @dev Checks before execution of an operation's calls. + @param id The 32-byte operation identifier. + @param predecessor The 32-byte hash of the preceding + operation. + """ + assert self._is_operation_ready(id), "TimelockController: operation is not ready" + assert predecessor == empty(bytes32) or self._is_operation_done(predecessor), "TimelockController: predecessor operation is not done" + + +@internal +def _after_call(id: bytes32): + """ + @dev Checks after execution of an operation's calls. + @param id The 32-byte operation identifier. + """ + assert self._is_operation_ready(id), "TimelockController: operation is not ready" + self.get_timestamp[id] = _DONE_TIMESTAMP + + +@internal +def _check_role(role: bytes32, account: address): + """ + @dev Sourced from {AccessControl-_check_role}. + @notice See {AccessControl-_check_role} for the + function docstring. """ assert self.hasRole[role][account], "AccessControl: account is missing role" @@ -806,11 +777,9 @@ def _check_role(role: bytes32, account: address): @internal def _set_role_admin(role: bytes32, admin_role: bytes32): """ - @dev Sets `admin_role` as `role`'s admin role. - @notice This is an `internal` function without - access restriction. - @param role The 32-byte role definition. - @param admin_role The new 32-byte admin role definition. + @dev Sourced from {AccessControl-_set_role_admin}. + @notice See {AccessControl-_set_role_admin} for the + function docstring. """ previous_admin_role: bytes32 = self.getRoleAdmin[role] self.getRoleAdmin[role] = admin_role @@ -820,11 +789,9 @@ def _set_role_admin(role: bytes32, admin_role: bytes32): @internal def _grant_role(role: bytes32, account: address): """ - @dev Grants `role` to `account`. - @notice This is an `internal` function without - access restriction. - @param role The 32-byte role definition. - @param account The 20-byte address of the account. + @dev Sourced from {AccessControl-_grant_role}. + @notice See {AccessControl-_grant_role} for the + function docstring. """ if (not(self.hasRole[role][account])): self.hasRole[role][account] = True @@ -834,11 +801,9 @@ def _grant_role(role: bytes32, account: address): @internal def _revoke_role(role: bytes32, account: address): """ - @dev Revokes `role` from `account`. - @notice This is an `internal` function without - access restriction. - @param role The 32-byte role definition. - @param account The 20-byte address of the account. + @dev Sourced from {AccessControl-_revoke_role}. + @notice See {AccessControl-_revoke_role} for the + function docstring. """ if (self.hasRole[role][account]): self.hasRole[role][account] = False From efc01ab038703f99c2312f4f2f767cdb62773482 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Sun, 21 Jan 2024 15:01:27 +0100 Subject: [PATCH 17/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20Amend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/auth/AccessControl.vy | 7 +- src/governance/TimelockController.vy | 531 ++++++++++++++++----------- src/tokens/ERC1155.vy | 3 + 3 files changed, 326 insertions(+), 215 deletions(-) diff --git a/src/auth/AccessControl.vy b/src/auth/AccessControl.vy index 0f6eec57..e4a5b14f 100644 --- a/src/auth/AccessControl.vy +++ b/src/auth/AccessControl.vy @@ -63,6 +63,9 @@ implements: IAccessControl # @dev The default 32-byte admin role. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. DEFAULT_ADMIN_ROLE: public(constant(bytes32)) = empty(bytes32) @@ -93,9 +96,6 @@ _SUPPORTED_INTERFACES: constant(bytes4[2]) = [ # @dev Returns `True` if `account` has been granted `role`. -# @notice If you declare a variable as `public`, -# Vyper automatically generates an `external` -# getter function for the variable. hasRole: public(HashMap[bytes32, HashMap[address, bool]]) @@ -226,6 +226,7 @@ def set_role_admin(role: bytes32, admin_role: bytes32): @internal +@view def _check_role(role: bytes32, account: address): """ @dev Reverts with a standard message if `account` diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 960e7961..5faf2d96 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -5,26 +5,32 @@ @license GNU Affero General Public License v3.0 only @author pcaversaccio @custom:coauthor cairoeth -@notice This module allows for timelocking operations by scheduling and - executing transactions. By leveraging AccessControl, the - TimelockController introduces three roles: proposer, executor, - and canceller. The proposer role is responsible for proposing - operations, the executor is responsible for executing scheduled - proposals, and the canceller is responsible for cancelling - proposals. The owner is the sole admin of the roles and can grant - and revoke them. In the constructor, proposers will be granted +@notice This module enables the timelocking of operations by scheduling + and executing transactions. By leveraging `AccessControl`, the + `TimelockController` contract introduces three roles: + 1. proposer (`PROPOSER_ROLE`), + 2. executor (`EXECUTOR_ROLE`), and + 3. canceller (`CANCELLER_ROLE`). + The proposer role is responsible for proposing operations, the executor + role is responsible for executing scheduled proposals, and the canceller + is responsible for cancelling proposals. This contract is self-administered + by default (unless an optional admin account is granted at construction), + meaning administration tasks (e.g. grant or revoke roles) have to go through + the timelock process. At contract creation time, proposers are granted the proposer and canceller roles. - Proposals must be scheduled with a delay that is greater than or - equal to the minimum delay (`minDelay()`), which can be updated via - a proposal to itself and is measured in seconds. Additionally, - proposals can be associated with preceding proposals, which must be - executed before the proposal can be executed. Ready proposals can be - executed by the executor, who is solely responsible for calling the - `execute()` function. + The proposals must be scheduled with a delay that is greater than or equal + to the minimum delay 'get_minimum_delay', which can be updated via a proposal + to itself and is measured in seconds. Additionally, proposals can be linked + to preceding proposals that must be executed before the proposal can be executed. - Proposals can be timelocked individually or in batches. The latter is - useful for operations that require execution in the same block. + Ready proposals can be executed by the executor, who is solely responsible + for calling the `execute` function. Eventually, the proposals can be batched + individually or in batches. The latter is useful for processes that have to + be executed in the same block. + + Please note that the `TimelockController` contract is able to receive and + transfer ERC-721 and ERC-1155 tokens. The implementation is inspired by OpenZeppelin's implementation here: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/TimelockController.sol. @@ -44,7 +50,24 @@ from ..auth.interfaces import IAccessControl implements: IAccessControl +# @dev We import and implement the `IERC721Receiver` +# interface, which is written using standard Vyper +# syntax. +from ..tokens.interfaces import IERC721Receiver +implements: IERC721Receiver + + +# @dev We import and implement the `IERC1155Receiver` +# interface, which is written using standard Vyper +# syntax. +from ..tokens.interfaces import IERC1155Receiver +implements: IERC1155Receiver + + # @dev The default 32-byte admin role. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. DEFAULT_ADMIN_ROLE: public(constant(bytes32)) = empty(bytes32) @@ -63,13 +86,26 @@ EXECUTOR_ROLE: public(constant(bytes32)) = keccak256("EXECUTOR_ROLE") CANCELLER_ROLE: public(constant(bytes32)) = keccak256("CANCELLER_ROLE") +# @dev The 4-byte function selector of `onERC721Received(address,address,uint256,bytes)`. +IERC721_TOKENRECEIVER_SELECTOR: public(constant(bytes4)) = 0x150B7A02 + + +# @dev The 4-byte function selector of `onERC1155Received(address,address,uint256,uint256,bytes)`. +IERC1155_TOKENRECEIVER_SINGLE_SELECTOR: public(constant(bytes4)) = 0xF23A6E61 + + +# @dev The 4-byte function selector of `onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)`. +IERC1155_TOKENRECEIVER_BATCH_SELECTOR: public(constant(bytes4)) = 0xBC197C81 + + # @dev Stores the ERC-165 interface identifier for each # imported interface. The ERC-165 interface identifier # is defined as the XOR of all function selectors in the # interface. -_SUPPORTED_INTERFACES: constant(bytes4[2]) = [ +_SUPPORTED_INTERFACES: constant(bytes4[3]) = [ 0x01FFC9A7, # The ERC-165 identifier for ERC-165. 0x7965DB0B, # The ERC-165 identifier for `IAccessControl`. + 0x4E2312E0, # The ERC-165 identifier for `IERC1155Receiver`. ] @@ -79,11 +115,12 @@ _DONE_TIMESTAMP: constant(uint256) = 1 # @dev The possible states of a proposal. -# @notice Enums are treated differently in Vyper and Solidity. -# The members are represented by `uint256` values (in Solidity -# the values are of type `uint8`) in the form `2**n`, where `n` -# is the index of the member in the range `0 <= n <= 255` (i.e. -# the first index value is 1). For further insights also, see +# @notice Enums are treated differently in Vyper and +# Solidity. The members are represented by `uint256` +# values (in Solidity the values are of type `uint8`) +# in the form `2**n`, where `n` is the index of the +# member in the range `0 <= n <= 255` (i.e. the first +# index value is `1`). For further insights also, see # the following Twitter thread: # https://twitter.com/pcaversaccio/status/1626514029094047747. enum OperationState: @@ -93,21 +130,19 @@ enum OperationState: DONE -# @dev Returns the timestamp at which an operation becomes -# ready (`0` for `UNSET` operations, `1` for `DONE` operations). +# @dev Returns the timestamp at which an operation +# becomes ready (`0` for `UNSET` operations, `1` for +# `DONE` operations). get_timestamp: public(HashMap[bytes32, uint256]) -# @dev Returns the minimum delay in seconds for an operation -# to become valid. This value can be changed by executing an -# operation that invokes `update_delay`. +# @dev Returns the minimum delay in seconds for an +# operation to become valid. This value can be changed +# by executing an operation that invokes `update_delay`. get_minimum_delay: public(uint256) # @dev Returns `True` if `account` has been granted `role`. -# @notice If you declare a variable as `public`, -# Vyper automatically generates an `external` -# getter function for the variable. hasRole: public(HashMap[bytes32, HashMap[address, bool]]) @@ -129,10 +164,10 @@ event CallScheduled: delay: uint256 -# @dev Emitted when a call is performed as part -# of operation `id`. Note that `index` is the -# index position of the proposal. If the proposal -# is individual, the `index` is `0`. +# @dev Emitted when a call is performed as part of +# operation `id`. Note that `index` is the index +# position of the proposal. If the proposal is +# individual, the `index` is `0`. event CallExecuted: id: indexed(bytes32) index: indexed(uint256) @@ -249,8 +284,8 @@ def __init__(minimum_delay_: uint256, proposers_: DynArray[address, 128], execut @payable def __default__(): """ - @dev Contract might receive/hold ETH as part of the - maintenance process. + @dev This contract might receive/hold ETH as part + of the maintenance process. """ pass @@ -336,35 +371,36 @@ def get_operation_state(id: bytes32) -> OperationState: @external @pure -def hash_operation(target: address, amount: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: +def hash_operation(target: address, amount: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: """ @dev Returns the identifier of an operation containing a single transaction. @param target The 20-bytes address of the target contract. - @param amount The 32-byte amount of native token to transfer + @param amount The 32-byte amount of native tokens to transfer with the call. - @param data The maximum 1,024-byte ABI-encoded calldata. - @param predecessor The 32-byte hash of the preceding - operation (optional with empty bytes). + @param payload The maximum 1,024-byte ABI-encoded calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). @param salt The 32-byte salt of the operation. @return bytes32 The 32-byte hash of the operation. """ - return self._hash_operation(target, amount, data, predecessor, salt) + return self._hash_operation(target, amount, payload, predecessor, salt) @external @pure -def hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ - predecessor: bytes32, salt: bytes32) -> bytes32: +def hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, + salt: bytes32) -> bytes32: """ @dev Returns the identifier of an operation containing a batch of transactions. - @param targets The 20-byte address of the targets contract. - @param amounts The 32-byte array of native token amounts to + @param targets The 20-byte array of the target contracts. + @param amounts The 32-byte array of native tokens amounts to transfer with each call. - @param data The maximum 1,024-byte array of ABI-encoded calldata. - @param predecessor The 32-byte hash of the preceding - operation (optional with empty bytes). + @param payloads The maximum 1,024-byte byte array of ABI-encoded + calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). @param salt The 32-byte salt of the operation. @return bytes32 The 32-byte hash of the operation. """ @@ -372,60 +408,58 @@ def hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint @external -def schedule(target: address, amount: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32, delay: uint256): +def schedule(target: address, amount: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32, delay: uint256): """ - @dev Schedule an operation containing a single transaction. - Emits `CallSalt` if salt is non-zero and `CallScheduled`. - @notice Requires the caller to have the `proposer` role. + @dev Schedules an operation containing a single transaction. + Emits `CallScheduled` and `CallSalt` if the salt is non-zero. + @notice Note that the caller must have the `PROPOSER_ROLE` role. @param target The 20-byte address of the target contract. - @param amount The 32-byte amount of native token to transfer + @param amount The 32-byte amount of native tokens to transfer with the call. - @param data The maximum 1,024-byte ABI-encoded calldata. - @param predecessor The hash of the preceding - operation. - @param salt The salt of the operation. - @param delay The delay before the operation - becomes valid. Must be greater than or - equal to the minimum delay. + @param payload The maximum 1,024-byte ABI-encoded calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). + @param salt The 32-byte salt of the operation. + @param delay The 32-byte delay before the operation becomes valid. + Must be greater than or equal to the minimum delay. """ self._check_role(PROPOSER_ROLE, msg.sender) - id: bytes32 = self._hash_operation(target, amount, data, predecessor, salt) + id: bytes32 = self._hash_operation(target, amount, payload, predecessor, salt) self._schedule(id, delay) - log CallScheduled(id, empty(uint256), target, amount, data, predecessor, delay) + log CallScheduled(id, empty(uint256), target, amount, payload, predecessor, delay) if (salt != empty(bytes32)): log CallSalt(id, salt) @external -def schedule_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ - predecessor: bytes32, salt: bytes32, delay: uint256): - """ - @dev Schedule an operation containing a batch - of transactions. Emits `CallSalt` if salt - is non-zero, and one `CallScheduled` event - per transaction in the batch. - @param targets The address of the target contracts. - @param amounts The amounts of native token to send - with the call. - @param payloads The ABI-encoded calls data. - @param predecessor The hash of the preceding - operation. - @param salt The salt of the operation. - @param delay The delay before the operation - becomes valid. Must be greater than or - equal to the minimum delay. - @notice Requires the caller to have the - `proposer` role. +def schedule_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, + salt: bytes32, delay: uint256): + """ + @dev Schedules an operation containing a batch of transactions. + Emits one `CallScheduled` event per transaction in the + batch and `CallSalt` if the salt is non-zero. + @notice Note that the caller must have the `PROPOSER_ROLE` role. + @param targets The 20-byte array of the target contracts. + @param amounts The 32-byte array of native tokens amounts to + transfer with each call. + @param payloads The maximum 1,024-byte byte array of ABI-encoded + calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). + @param salt The 32-byte salt of the operation. + @param delay The 32-byte delay before the operation becomes valid. + Must be greater than or equal to the minimum delay. """ self._check_role(PROPOSER_ROLE, msg.sender) - assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: invalid operation length" + assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: length mismatch" id: bytes32 = self._hash_operation_batch(targets, amounts, payloads, predecessor, salt) self._schedule(id, delay) idx: uint256 = empty(uint256) for target in targets: log CallScheduled(id, idx, target, amounts[idx], payloads[idx], predecessor, delay) # The following line cannot overflow because we have - # limited the dynamic array. + # limited the dynamic array `targets` by the maximum + # value of `128`. idx = unsafe_add(idx, 1) if (salt != empty(bytes32)): log CallSalt(id, salt) @@ -434,9 +468,8 @@ def schedule_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 1 @external def cancel(id: bytes32): """ - @dev Cancel an operation. - @notice Requires the caller to have the - `canceller` role. + @dev Cancels an operation. + @notice Note that the caller must have the `CANCELLER_ROLE` role. @param id The 32-byte operation identifier. """ self._check_role(CANCELLER_ROLE, msg.sender) @@ -449,21 +482,20 @@ def cancel(id: bytes32): @payable def execute(target: address, amount: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32): """ - @dev Execute an (ready) operation - containing a single transaction. + @dev Executes a ready operation containing a single transaction. Emits a `CallExecuted` event. - @param target The address of the target contract. - @param amount The amount of native token to send + @notice Note that the caller must have the `EXECUTOR_ROLE` role. + @param target The 20-byte address of the target contract. + @param amount The 32-byte amount of native tokens to transfer with the call. - @param payload The ABI-encoded call data. - @param predecessor The hash of the preceding - operation. - @param salt The salt of the operation. - @notice Requires the caller to have the `executor` role. - This function can reenter, but it doesn't pose - a risk because `_afterCall` checks that the - proposal is pending, thus any modifications to - the operation during reentrancy should be caught. + @param payload The maximum 1,024-byte ABI-encoded calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). + @param salt The 32-byte salt of the operation. + @custom:security This function can reenter, but it doesn't pose + a risk because `_after_call` checks that the proposal is + pending, thus any modifications to the operation during + reentrancy are caught. """ self._only_role_or_open_role(EXECUTOR_ROLE) id: bytes32 = self._hash_operation(target, amount, payload, predecessor, salt) @@ -476,28 +508,27 @@ def execute(target: address, amount: uint256, payload: Bytes[1_024], predecessor @external @payable -def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ - predecessor: bytes32, salt: bytes32): - """ - @dev Execute an (ready) operation - containing a batch of transactions. - Emits one `CallExecuted` event per - transaction in the batch. - @param targets The address of the target contracts. - @param amounts The amounts of native token to send - with the call. - @param payloads The ABI-encoded calls data. - @param predecessor The hash of the preceding - operation. - @param salt The salt of the operation. - @notice Requires the caller to have the `executor` role. - This function can reenter, but it doesn't pose - a risk because `_afterCall` checks that the - proposal is pending, thus any modifications to - the operation during reentrancy should be caught. +def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, + salt: bytes32): + """ + @dev Executes a ready operation containing a batch of transactions. + Emits one `CallExecuted` event per transaction in the batch. + @notice Note that the caller must have the `EXECUTOR_ROLE` role. + @param targets The 20-byte array of the target contracts. + @param amounts The 32-byte array of native tokens amounts to + transfer with each call. + @param payloads The maximum 1,024-byte byte array of ABI-encoded + calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). + @param salt The 32-byte salt of the operation. + @custom:security This function can reenter, but it doesn't pose + a risk because `_after_call` checks that the proposal is + pending, thus any modifications to the operation during + reentrancy are caught. """ self._only_role_or_open_role(EXECUTOR_ROLE) - assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: invalid operation length" + assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: length mismatch" id: bytes32 = self._hash_operation_batch(targets, amounts, payloads, predecessor, salt) self._before_call(id, predecessor) @@ -506,7 +537,8 @@ def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 12 self._execute(target, amounts[idx], payloads[idx]) log CallExecuted(id, idx, target, amounts[idx], payloads[idx]) # The following line cannot overflow because we have - # limited the dynamic array. + # limited the dynamic array `targets` by the maximum + # value of `128`. idx = unsafe_add(idx, 1) self._after_call(id) @@ -515,15 +547,15 @@ def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 12 def update_delay(new_delay: uint256): """ @dev Changes the minimum timelock duration for future - operations. Emits a `MinDelayChange` event. - @param newDelay The new minimum delay in seconds. - @notice Requires the caller to be the timelock itself. - This can only be achieved by scheduling and - later executing an operation where the timelock - is the target and the data is the ABI-encoded + operations. Emits a `MinimumDelayChange` event. + @notice Note that the caller must be the `TimelockController` + contract itself. This can only be achieved by scheduling + and later executing an operation where the `TimelockController` + contract is the target and the payload is the ABI-encoded call to this function. + @param new_delay The new 32-byte minimum delay in seconds. """ - assert msg.sender == self, "TimelockController: unauthorised" + assert msg.sender == self, "TimelockController: caller must be timelock" log MinimumDelayChange(self.get_minimum_delay, new_delay) self.get_minimum_delay = new_delay @@ -531,13 +563,9 @@ def update_delay(new_delay: uint256): @external def grantRole(role: bytes32, account: address): """ - @dev Grants `role` to `account`. - @notice If `account` had not been already - granted `role`, emits a `RoleGranted` - event. Note that the caller must have - `role`'s admin role. - @param role The 32-byte role definition. - @param account The 20-byte address of the account. + @dev Sourced from {AccessControl-grantRole}. + @notice See {AccessControl-grantRole} for the + function docstring. """ self._check_role(self.getRoleAdmin[role], msg.sender) self._grant_role(role, account) @@ -546,12 +574,9 @@ def grantRole(role: bytes32, account: address): @external def revokeRole(role: bytes32, account: address): """ - @dev Revokes `role` from `account`. - @notice If `account` had been granted `role`, - emits a `RoleRevoked` event. Note that - the caller must have `role`'s admin role. - @param role The 32-byte role definition. - @param account The 20-byte address of the account. + @dev Sourced from {AccessControl-revokeRole}. + @notice See {AccessControl-revokeRole} for the + function docstring. """ self._check_role(self.getRoleAdmin[role], msg.sender) self._revoke_role(role, account) @@ -560,17 +585,9 @@ def revokeRole(role: bytes32, account: address): @external def renounceRole(role: bytes32, account: address): """ - @dev Revokes `role` from the calling account. - @notice Roles are often managed via `grantRole` - and `revokeRole`. This function's purpose - is to provide a mechanism for accounts to - lose their privileges if they are compromised - (such as when a trusted device is misplaced). - If the calling account had been granted `role`, - emits a `RoleRevoked` event. Note that the - caller must be `account`. - @param role The 32-byte role definition. - @param account The 20-byte address of the account. + @dev Sourced from {AccessControl-renounceRole}. + @notice See {AccessControl-renounceRole} for the + function docstring. """ assert account == msg.sender, "AccessControl: can only renounce roles for itself" self._revoke_role(role, account) @@ -579,47 +596,109 @@ def renounceRole(role: bytes32, account: address): @external def set_role_admin(role: bytes32, admin_role: bytes32): """ - @dev Sets `admin_role` as `role`'s admin role. - @notice Note that the caller must have `role`'s - admin role. - @param role The 32-byte role definition. - @param admin_role The new 32-byte admin role definition. + @dev Sourced from {AccessControl-set_role_admin}. + @notice See {AccessControl-set_role_admin} for the + function docstring. """ self._check_role(self.getRoleAdmin[role], msg.sender) self._set_role_admin(role, admin_role) +@external +def onERC721Received(operator: address, owner: address, token_id: uint256, data: Bytes[1_024]) -> bytes4: + """ + @dev Whenever a `token_id` token is transferred to + this contract via `safeTransferFrom` by + `operator` from `owner`, this function is called. + @notice It must return its function selector to + confirm the token transfer. If any other value + is returned or the interface is not implemented + by the recipient, the transfer will be reverted. + @param operator The 20-byte address which called + the `safeTransferFrom` function. + @param owner The 20-byte address which previously + owned the token. + @param token_id The 32-byte identifier of the token. + @param data The maximum 1,024-byte additional data + with no specified format. + @return bytes4 The 4-byte function selector of `onERC721Received`. + """ + return IERC721_TOKENRECEIVER_SELECTOR + + +@external +def onERC1155Received(operator: address, owner: address, id: uint256, amount: uint256, data: Bytes[1_024]) -> bytes4: + """ + @dev Handles the receipt of a single ERC-1155 token type. + This function is called at the end of a `safeTransferFrom` + after the balance has been updated. + @notice It must return its function selector to + confirm the token transfer. If any other value + is returned or the interface is not implemented + by the recipient, the transfer will be reverted. + @param operator The 20-byte address which called + the `safeTransferFrom` function. + @param owner The 20-byte address which previously + owned the token. + @param id The 32-byte identifier of the token. + @param amount The 32-byte token amount that is + being transferred. + @param data The maximum 1,024-byte additional data + with no specified format. + @return bytes4 The 4-byte function selector of `onERC1155Received`. + """ + return IERC1155_TOKENRECEIVER_SINGLE_SELECTOR + + +@external +def onERC1155BatchReceived(operator: address, owner: address, ids: DynArray[uint256, 65_535], amounts: DynArray[uint256, 65_535], + data: Bytes[1_024]) -> bytes4: + """ + @dev Handles the receipt of multiple ERC-1155 token types. + This function is called at the end of a `safeBatchTransferFrom` + after the balances have been updated. + @notice It must return its function selector to + confirm the token transfers. If any other value + is returned or the interface is not implemented + by the recipient, the transfers will be reverted. + @param operator The 20-byte address which called + the `safeBatchTransferFrom` function. + @param owner The 20-byte address which previously + owned the tokens. + @param ids The 32-byte array of token identifiers. Note + that the order and length must match the 32-byte + `_values` array. + @param amounts The 32-byte array of token amounts that are + being transferred. Note that the order and length must + match the 32-byte `_ids` array. + @param data The maximum 1,024-byte additional data + with no specified format. + @return bytes4 The 4-byte function selector of `onERC1155BatchReceived`. + """ + return IERC1155_TOKENRECEIVER_BATCH_SELECTOR + + @internal @view def _is_operation(id: bytes32) -> bool: """ - @dev Internal logic of `isOperation`. + @dev Returns whether an `id` corresponds to a registered + operation. This includes both `WAITING`, `READY`, and + `DONE` operations. @param id The 32-byte operation identifier. - @return bool The verification whether the id + @return bool The verification whether the `id` corresponds to a registered operation or not. """ return self._get_operation_state(id) != OperationState.UNSET -@internal -def _only_role_or_open_role(role: bytes32): - """ - @dev Used to limit a function to be callable only by - a certain role. In addition to checking the - sender's role, `empty(address)` is also - considered. Granting a role to `empty(address)` - is equivalent to enabling this role for everyone. - @param role The 32-byte role definition. - """ - if (not(self.hasRole[role][empty(address)])): - self._check_role(role, msg.sender) - - @internal @view def _is_operation_pending(id: bytes32) -> bool: """ - @dev Internal logic of `isOperationPending`. + @dev Returns whether an operation is pending or not. + Note that a "pending" operation may also be + "ready". @param id The 32-byte operation identifier. @return bool The verification whether the operation is pending or not. @@ -632,10 +711,12 @@ def _is_operation_pending(id: bytes32) -> bool: @view def _is_operation_ready(id: bytes32) -> bool: """ - @dev Internal logic of `_isOperationReady`. + @dev Returns whether an operation is ready for + execution. Note that a "ready" operation is + also "pending". @param id The 32-byte operation identifier. - @return bool The verification whether - the operation is ready or not. + @return bool The verification whether the operation + is ready or not. """ return self._get_operation_state(id) == OperationState.READY @@ -644,10 +725,10 @@ def _is_operation_ready(id: bytes32) -> bool: @view def _is_operation_done(id: bytes32) -> bool: """ - @dev Internal logic of `_isOperationDone`. + @dev Returns whether an operation is done or not. @param id The 32-byte operation identifier. - @return bool The verification whether - the operation is done or not. + @return bool The verification whether the operation + is done or not. """ return self._get_operation_state(id) == OperationState.DONE @@ -656,9 +737,9 @@ def _is_operation_done(id: bytes32) -> bool: @view def _get_operation_state(id: bytes32) -> OperationState: """ - @dev Internal logic of `_getOperationState`. + @dev Returns the state of an operation. @param id The 32-byte operation identifier. - @return OperationState The state of the + @return OperationState The 32-byte state of the operation. """ timestamp: uint256 = self.get_timestamp[id] @@ -674,35 +755,38 @@ def _get_operation_state(id: bytes32) -> OperationState: @internal @pure -def _hash_operation(target: address, amount: uint256, data: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: +def _hash_operation(target: address, amount: uint256, payload: Bytes[1_024], predecessor: bytes32, salt: bytes32) -> bytes32: """ - @dev Internal logic of `hashOperation`. - @param target The address of the target contract. - @param amount The amount of native token to send + @dev Returns the identifier of an operation containing + a single transaction. + @param target The 20-bytes address of the target contract. + @param amount The 32-byte amount of native tokens to transfer with the call. - @param data The ABI-encoded call data. - @param predecessor The hash of the preceding - operation (optional with empty bytes). - @param salt The salt of the operation. - @return bytes32 The hash of the operation. + @param payload The maximum 1,024-byte ABI-encoded calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). + @param salt The 32-byte salt of the operation. + @return bytes32 The 32-byte hash of the operation. """ - return keccak256(_abi_encode(target, amount, data, predecessor, salt)) + return keccak256(_abi_encode(target, amount, payload, predecessor, salt)) @internal @pure -def _hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128],\ - predecessor: bytes32, salt: bytes32) -> bytes32: - """ - @dev An `internal` helper function that returns `hash_operationBatch`. - @param targets The address of the targets contract. - @param amounts The amounts of native token to send - with each call. - @param payloads The ABI-encoded calls data. - @param predecessor The hash of the preceding - operation (optional with empty bytes). - @param salt The salt of the operation. - @return bytes32 The hash of the operation. +def _hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, + salt: bytes32) -> bytes32: + """ + @dev Returns the identifier of an operation containing + a batch of transactions. + @param targets The 20-byte array of the target contracts. + @param amounts The 32-byte array of native tokens amounts to + transfer with each call. + @param payloads The maximum 1,024-byte byte array of ABI-encoded + calldata. + @param predecessor The 32-byte hash of the preceding operation + (optional with empty bytes). + @param salt The 32-byte salt of the operation. + @return bytes32 The 32-byte hash of the operation. """ return keccak256(_abi_encode(targets, amounts, payloads, predecessor, salt)) @@ -712,6 +796,8 @@ def _schedule(id: bytes32, delay: uint256): """ @dev Schedules an operation that is to become valid after a given delay. + @notice This is an `internal` function without access + restriction. @param id The 32-byte operation identifier. @param delay The 32-byte delay before the operation becomes valid. Must be greater than or equal @@ -725,17 +811,20 @@ def _schedule(id: bytes32, delay: uint256): @internal def _execute(target: address, amount: uint256, payload: Bytes[1_024]): """ - @dev Executes an operation's call. + @dev Executes an operation call. + @notice This is an `internal` function without access + restriction. @param target The 20-byte address of the target contract. - @param amount The 32-byte amount of native token to transfer + @param amount The 32-byte amount of native tokens to transfer with the call. - @param data The maximum 1,024-byte array of ABI-encoded calldata. + @param payload The maximum 1,024-byte ABI-encoded calldata. """ return_data: Bytes[max_value(uint8)] = b"" success: bool = empty(bool) success, return_data = raw_call(target, payload, max_outsize=255, value=amount, revert_on_failure=False) if (not(success)): - if len(return_data) != 0: + if len(return_data) != empty(uint256): + # We bubble up the revert reason. raw_revert(return_data) else: raise "TimelockController: underlying transaction reverted" @@ -745,19 +834,21 @@ def _execute(target: address, amount: uint256, payload: Bytes[1_024]): @view def _before_call(id: bytes32, predecessor: bytes32): """ - @dev Checks before execution of an operation's calls. + @dev Implements safety checks that must succeed before + executing (an) operation call(s). @param id The 32-byte operation identifier. @param predecessor The 32-byte hash of the preceding operation. """ assert self._is_operation_ready(id), "TimelockController: operation is not ready" - assert predecessor == empty(bytes32) or self._is_operation_done(predecessor), "TimelockController: predecessor operation is not done" + assert predecessor == empty(bytes32) or self._is_operation_done(predecessor), "TimelockController: missing dependency" @internal def _after_call(id: bytes32): """ - @dev Checks after execution of an operation's calls. + @dev Implements safety checks that must succeed after + executing (an) operation call(s). @param id The 32-byte operation identifier. """ assert self._is_operation_ready(id), "TimelockController: operation is not ready" @@ -765,6 +856,22 @@ def _after_call(id: bytes32): @internal +@view +def _only_role_or_open_role(role: bytes32): + """ + @dev Limits a function to be callable only by a certain + role. In addition to checking the sender's role, + the zero address `empty(address)` is also considered. + Granting a role to `empty(address)` is equivalent to + enabling this role for everyone. + @param role The 32-byte role definition. + """ + if (not(self.hasRole[role][empty(address)])): + self._check_role(role, msg.sender) + + +@internal +@view def _check_role(role: bytes32, account: address): """ @dev Sourced from {AccessControl-_check_role}. diff --git a/src/tokens/ERC1155.vy b/src/tokens/ERC1155.vy index 4b96fbfc..1741e467 100644 --- a/src/tokens/ERC1155.vy +++ b/src/tokens/ERC1155.vy @@ -76,6 +76,9 @@ _BASE_URI: immutable(String[80]) # @dev Mapping from owner to operator approvals. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. isApprovedForAll: public(HashMap[address, HashMap[address, bool]]) From ac2b9c7d6911018c43297d80fe22df4f1cade959 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Sun, 21 Jan 2024 17:11:59 +0100 Subject: [PATCH 18/46] =?UTF-8?q?=F0=9F=93=96=20Add=20Missing=20Comments?= =?UTF-8?q?=20in=20Other=20Contracts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/auth/Ownable.vy | 3 +++ src/auth/Ownable2Step.vy | 3 +++ src/extensions/ERC2981.vy | 3 +++ src/utils/Create2Address.vy | 3 +++ src/utils/ECDSA.vy | 1 + src/utils/SignatureChecker.vy | 7 +++++++ 6 files changed, 20 insertions(+) diff --git a/src/auth/Ownable.vy b/src/auth/Ownable.vy index b5f07671..256b2cb3 100644 --- a/src/auth/Ownable.vy +++ b/src/auth/Ownable.vy @@ -17,6 +17,9 @@ # @dev Returns the address of the current owner. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. owner: public(address) diff --git a/src/auth/Ownable2Step.vy b/src/auth/Ownable2Step.vy index 9a09bbb5..d4aa02c5 100644 --- a/src/auth/Ownable2Step.vy +++ b/src/auth/Ownable2Step.vy @@ -16,6 +16,9 @@ # @dev Returns the address of the current owner. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. owner: public(address) diff --git a/src/extensions/ERC2981.vy b/src/extensions/ERC2981.vy index 390c510d..32e6cf65 100644 --- a/src/extensions/ERC2981.vy +++ b/src/extensions/ERC2981.vy @@ -67,6 +67,9 @@ _SUPPORTED_INTERFACES: constant(bytes4[2]) = [ # @dev Returns the address of the current owner. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. owner: public(address) diff --git a/src/utils/Create2Address.vy b/src/utils/Create2Address.vy index 70b11833..15afc21e 100644 --- a/src/utils/Create2Address.vy +++ b/src/utils/Create2Address.vy @@ -12,6 +12,9 @@ """ +# @dev The `CREATE2` offset constant used to prevent +# collisions with addresses created using the traditional +# `keccak256(rlp([sender, nonce]))` formula. _COLLISION_OFFSET: constant(bytes1) = 0xFF diff --git a/src/utils/ECDSA.vy b/src/utils/ECDSA.vy index e5d85aae..78f1f9d1 100644 --- a/src/utils/ECDSA.vy +++ b/src/utils/ECDSA.vy @@ -18,6 +18,7 @@ """ +# @dev Constants used as part of the ECDSA recovery function. _MALLEABILITY_THRESHOLD: constant(bytes32) = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 _SIGNATURE_INCREMENT: constant(bytes32) = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF diff --git a/src/utils/SignatureChecker.vy b/src/utils/SignatureChecker.vy index 71e6c859..68371c15 100644 --- a/src/utils/SignatureChecker.vy +++ b/src/utils/SignatureChecker.vy @@ -22,7 +22,14 @@ """ +# @dev The 4-byte function selector of `isValidSignature(bytes32,bytes)`. +# @notice If you declare a variable as `public`, +# Vyper automatically generates an `external` +# getter function for the variable. IERC1271_ISVALIDSIGNATURE_SELECTOR: public(constant(bytes4)) = 0x1626BA7E + + +# @dev Constants used as part of the ECDSA recovery function. _MALLEABILITY_THRESHOLD: constant(bytes32) = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 _SIGNATURE_INCREMENT: constant(bytes32) = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF From 669abb6323e7e6fa5eea31631dc7ee05e8b6be47 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Sun, 21 Jan 2024 18:14:14 +0100 Subject: [PATCH 19/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20Further=20chore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 60 +++++++++++++++------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 5faf2d96..5a4bc909 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -8,29 +8,31 @@ @notice This module enables the timelocking of operations by scheduling and executing transactions. By leveraging `AccessControl`, the `TimelockController` contract introduces three roles: - 1. proposer (`PROPOSER_ROLE`), - 2. executor (`EXECUTOR_ROLE`), and - 3. canceller (`CANCELLER_ROLE`). - The proposer role is responsible for proposing operations, the executor - role is responsible for executing scheduled proposals, and the canceller - is responsible for cancelling proposals. This contract is self-administered - by default (unless an optional admin account is granted at construction), - meaning administration tasks (e.g. grant or revoke roles) have to go through - the timelock process. At contract creation time, proposers are granted - the proposer and canceller roles. - - The proposals must be scheduled with a delay that is greater than or equal - to the minimum delay 'get_minimum_delay', which can be updated via a proposal - to itself and is measured in seconds. Additionally, proposals can be linked - to preceding proposals that must be executed before the proposal can be executed. - - Ready proposals can be executed by the executor, who is solely responsible - for calling the `execute` function. Eventually, the proposals can be batched - individually or in batches. The latter is useful for processes that have to - be executed in the same block. - - Please note that the `TimelockController` contract is able to receive and - transfer ERC-721 and ERC-1155 tokens. + 1. proposer (`PROPOSER_ROLE`), + 2. executor (`EXECUTOR_ROLE`), and + 3. canceller (`CANCELLER_ROLE`). + The proposer role is responsible for proposing operations, the + executor role is responsible for executing scheduled proposal(s), + and the canceller is responsible for cancelling proposal(s). This + contract is self-administered by default (unless an optional admin + account is granted at construction), meaning administration tasks + (e.g. grant or revoke roles) have to go through the timelock process. + At contract creation time, proposers are granted the proposer and + canceller roles. + + The proposal(s) must be scheduled with a delay that is greater + than or equal to the minimum delay `get_minimum_delay`, which can + be updated via a proposal to itself and is measured in seconds. + Additionally, proposal(s) can be linked to preceding proposal(s) + that must be executed before the proposal can be executed. + + Ready proposal(s) can be executed by the executor, who is solely + responsible for calling the `execute` function. Eventually, the + proposal(s) can be batched individually or in batches. The latter + is useful for processes that have to be executed in the same block. + + Please note that the `TimelockController` contract is able to receive + and transfer ERC-721 and ERC-1155 tokens. The implementation is inspired by OpenZeppelin's implementation here: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/TimelockController.sol. @@ -158,7 +160,7 @@ event CallScheduled: id: indexed(bytes32) index: indexed(uint256) target: address - value: uint256 + amount: uint256 data: Bytes[1_024] predecessor: bytes32 delay: uint256 @@ -172,7 +174,7 @@ event CallExecuted: id: indexed(bytes32) index: indexed(uint256) target: address - value: uint256 + amount: uint256 data: Bytes[1_024] @@ -425,6 +427,7 @@ def schedule(target: address, amount: uint256, payload: Bytes[1_024], predecesso """ self._check_role(PROPOSER_ROLE, msg.sender) id: bytes32 = self._hash_operation(target, amount, payload, predecessor, salt) + self._schedule(id, delay) log CallScheduled(id, empty(uint256), target, amount, payload, predecessor, delay) if (salt != empty(bytes32)): @@ -453,6 +456,7 @@ def schedule_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 1 self._check_role(PROPOSER_ROLE, msg.sender) assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: length mismatch" id: bytes32 = self._hash_operation_batch(targets, amounts, payloads, predecessor, salt) + self._schedule(id, delay) idx: uint256 = empty(uint256) for target in targets: @@ -608,7 +612,7 @@ def set_role_admin(role: bytes32, admin_role: bytes32): def onERC721Received(operator: address, owner: address, token_id: uint256, data: Bytes[1_024]) -> bytes4: """ @dev Whenever a `token_id` token is transferred to - this contract via `safeTransferFrom` by + this contract via ERC-721 `safeTransferFrom` by `operator` from `owner`, this function is called. @notice It must return its function selector to confirm the token transfer. If any other value @@ -667,10 +671,10 @@ def onERC1155BatchReceived(operator: address, owner: address, ids: DynArray[uint owned the tokens. @param ids The 32-byte array of token identifiers. Note that the order and length must match the 32-byte - `_values` array. + `amounts` array. @param amounts The 32-byte array of token amounts that are being transferred. Note that the order and length must - match the 32-byte `_ids` array. + match the 32-byte `ids` array. @param data The maximum 1,024-byte additional data with no specified format. @return bytes4 The 4-byte function selector of `onERC1155BatchReceived`. From 31a1af17fe69285fd63481097354106653817abc Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Sun, 21 Jan 2024 18:20:06 +0100 Subject: [PATCH 20/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20Further=20chore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 5a4bc909..10885850 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -497,9 +497,9 @@ def execute(target: address, amount: uint256, payload: Bytes[1_024], predecessor (optional with empty bytes). @param salt The 32-byte salt of the operation. @custom:security This function can reenter, but it doesn't pose - a risk because `_after_call` checks that the proposal is - pending, thus any modifications to the operation during - reentrancy are caught. + a risk because `_after_call` checks that the + proposal is pending, thus any modifications to + the operation during reentrancy are caught. """ self._only_role_or_open_role(EXECUTOR_ROLE) id: bytes32 = self._hash_operation(target, amount, payload, predecessor, salt) @@ -527,9 +527,9 @@ def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 12 (optional with empty bytes). @param salt The 32-byte salt of the operation. @custom:security This function can reenter, but it doesn't pose - a risk because `_after_call` checks that the proposal is - pending, thus any modifications to the operation during - reentrancy are caught. + a risk because `_after_call` checks that the + proposal is pending, thus any modifications to + the operation during reentrancy are caught. """ self._only_role_or_open_role(EXECUTOR_ROLE) assert len(targets) == len(amounts) and len(targets) == len(payloads), "TimelockController: length mismatch" From 4ec4ada4a8196655cd675b4126f739bde4e774b9 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Sun, 21 Jan 2024 18:29:18 +0100 Subject: [PATCH 21/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 10885850..e4cdc274 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -235,13 +235,13 @@ event RoleRevoked: def __init__(minimum_delay_: uint256, proposers_: DynArray[address, 128], executors_: DynArray[address, 128], admin_: address): """ @dev Initialises the contract with the following parameters: - - `minimum_delay_`: The initial minimum delay in seconds - for operations, - - `proposers_`: The accounts to be granted proposer and - canceller roles, - - `executors_`: The accounts to be granted executor role, - - `admin_`: The optional account to be granted admin role - (disable with the zero address). + - `minimum_delay_`: The initial minimum delay in seconds + for operations, + - `proposers_`: The accounts to be granted proposer and + canceller roles, + - `executors_`: The accounts to be granted executor role, + - `admin_`: The optional account to be granted admin role + (disable with the zero address). IMPORTANT: The optional admin can aid with initial configuration of roles after deployment without being From b852bc5a4da232430974a9bc1356fca27bd68a75 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Mon, 22 Jan 2024 13:01:56 +0100 Subject: [PATCH 22/46] =?UTF-8?q?=F0=9F=93=96=20Finetune=20wording?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index e4cdc274..6fff2d48 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -27,9 +27,10 @@ that must be executed before the proposal can be executed. Ready proposal(s) can be executed by the executor, who is solely - responsible for calling the `execute` function. Eventually, the - proposal(s) can be batched individually or in batches. The latter - is useful for processes that have to be executed in the same block. + responsible for calling the `execute` or `execute_batch` functions. + Eventually, the proposal(s) can be batched individually or in batches. + The latter is useful for processes that have to be executed in the + same block. Please note that the `TimelockController` contract is able to receive and transfer ERC-721 and ERC-1155 tokens. @@ -104,6 +105,10 @@ IERC1155_TOKENRECEIVER_BATCH_SELECTOR: public(constant(bytes4)) = 0xBC197C81 # imported interface. The ERC-165 interface identifier # is defined as the XOR of all function selectors in the # interface. +# @notice Note that the ERC-165 interface identifier for +# the `ERC721TokenReceiver` interface is not included as +# it is not required by the EIP: +# https://eips.ethereum.org/EIPS/eip-721#specification. _SUPPORTED_INTERFACES: constant(bytes4[3]) = [ 0x01FFC9A7, # The ERC-165 identifier for ERC-165. 0x7965DB0B, # The ERC-165 identifier for `IAccessControl`. @@ -828,7 +833,7 @@ def _execute(target: address, amount: uint256, payload: Bytes[1_024]): success, return_data = raw_call(target, payload, max_outsize=255, value=amount, revert_on_failure=False) if (not(success)): if len(return_data) != empty(uint256): - # We bubble up the revert reason. + # Bubble up the revert reason. raw_revert(return_data) else: raise "TimelockController: underlying transaction reverted" From bf6ccf54ab4c4e8a2e536ff65797146dc64836a7 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Mon, 22 Jan 2024 13:49:52 +0100 Subject: [PATCH 23/46] =?UTF-8?q?=E2=9C=85=20Fix=20tests=20with=20interfac?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 320 +++++++++--------- .../interfaces/ITimelockController.sol | 62 ++++ 2 files changed, 220 insertions(+), 162 deletions(-) create mode 100644 test/governance/interfaces/ITimelockController.sol diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 2ae6df4c..3a76857f 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import {Test} from "forge-std/Test.sol"; import {VyperDeployer} from "utils/VyperDeployer.sol"; -import {TimelockController} from "openzeppelin/governance/TimelockController.sol"; +import {ITimelockController} from "./interfaces/ITimelockController.sol"; contract TimelockControllerTest is Test { uint256 internal constant MIN_DELAY = 2 days; @@ -37,7 +37,7 @@ contract TimelockControllerTest is Test { VyperDeployer private vyperDeployer = new VyperDeployer(); - TimelockController private timelockController; + ITimelockController private timelockController; address private deployer = address(vyperDeployer); @@ -57,7 +57,7 @@ contract TimelockControllerTest is Test { executors[1] = EXECUTOR_TWO; bytes memory args = abi.encode(MIN_DELAY, proposers, executors, ADMIN); - timelockController = TimelockController( + timelockController = ITimelockController( payable( vyperDeployer.deployContract( "src/governance/", @@ -86,7 +86,7 @@ contract TimelockControllerTest is Test { } function checkRoleNotSetForAddresses( - TimelockController timelock, + ITimelockController timelock, bytes32 role, address[2] storage addresses ) internal { @@ -168,7 +168,7 @@ contract TimelockControllerTest is Test { timelockController.EXECUTOR_ROLE(), PROPOSERS ); - assertEq(timelockController.getMinDelay(), MIN_DELAY); + assertEq(timelockController.get_minimum_delay(), MIN_DELAY); // TODO: Add event emit checks. } @@ -193,7 +193,7 @@ contract TimelockControllerTest is Test { bytes32 predecessor = NO_PREDECESSOR; bytes32 salt = EMPTY_SALT; - bytes32 hashedOperation = timelockController.hashOperationBatch( + bytes32 hashedOperation = timelockController.hash_operation_batch( targets, values, payloads, @@ -208,17 +208,17 @@ contract TimelockControllerTest is Test { event MinDelayChange(uint256 oldDuration, uint256 newDuration); - function testRevertWhenNotAdminRole() public { - vm.expectRevert("TimelockController: unauthorized"); + function testRevertWhenNotTimelock() public { + vm.expectRevert("TimelockController: caller must be timelock"); vm.prank(STRANGER); - timelockController.updateDelay(3 days); + timelockController.update_delay(3 days); } function testUpdatesMinDelay() public { address target = address(timelockController); uint256 value = 0; bytes memory data = abi.encodeWithSelector( - timelockController.updateDelay.selector, + timelockController.update_delay.selector, MIN_DELAY ); @@ -240,7 +240,7 @@ contract TimelockControllerTest is Test { vm.prank(EXECUTOR_ONE); timelockController.execute(target, value, data, predecessor, salt); - uint256 minDelay = timelockController.getMinDelay(); + uint256 minDelay = timelockController.get_minimum_delay(); assertEq(minDelay, 2 days); } @@ -248,7 +248,7 @@ contract TimelockControllerTest is Test { address target = address(timelockController); uint256 value = 0; bytes memory data = abi.encodeWithSelector( - timelockController.updateDelay.selector, + timelockController.update_delay.selector, 0 ); @@ -269,12 +269,12 @@ contract TimelockControllerTest is Test { function testUpdatesDelayAtLeastMinDelay() public { vm.prank(address(timelockController)); - timelockController.updateDelay(0); // set min delay to 0 + timelockController.update_delay(0); // set min delay to 0 address target = address(timelockController); uint256 value = 0; bytes memory data = abi.encodeWithSelector( - timelockController.updateDelay.selector, + timelockController.update_delay.selector, MIN_DELAY ); @@ -296,7 +296,7 @@ contract TimelockControllerTest is Test { vm.prank(EXECUTOR_ONE); timelockController.execute(target, value, data, predecessor, salt); - uint256 minDelay = timelockController.getMinDelay(); + uint256 minDelay = timelockController.get_minimum_delay(); assertEq(minDelay, MIN_DELAY); } @@ -307,7 +307,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -317,7 +317,7 @@ contract TimelockControllerTest is Test { ); } - function _scheduleBatchedOperation() + function _schedule_batchedOperation() internal view returns ( @@ -342,9 +342,9 @@ contract TimelockControllerTest is Test { address[] memory targets, uint256[] memory values, bytes[] memory payloads - ) = _scheduleBatchedOperation(); + ) = _schedule_batchedOperation(); - bytes32 batchedOperationID = timelockController.hashOperationBatch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -352,10 +352,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - assertEq(timelockController.isOperation(batchedOperationID), false); + assertEq(timelockController.is_operation(batchedOperationID), false); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -364,7 +364,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - assertEq(timelockController.isOperation(batchedOperationID), true); + assertEq(timelockController.is_operation(batchedOperationID), true); } function testAdminCantBatchSchedule() public { @@ -372,9 +372,9 @@ contract TimelockControllerTest is Test { address[] memory targets, uint256[] memory values, bytes[] memory payloads - ) = _scheduleBatchedOperation(); + ) = _schedule_batchedOperation(); - bytes32 batchedOperationID = timelockController.hashOperationBatch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -382,11 +382,11 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - assertEq(timelockController.isOperation(batchedOperationID), false); + assertEq(timelockController.is_operation(batchedOperationID), false); vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -395,7 +395,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - assertEq(timelockController.isOperation(batchedOperationID), false); + assertEq(timelockController.is_operation(batchedOperationID), false); } function testRevertWhenScheduleIfOperationScheduled() public { @@ -409,7 +409,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.startPrank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -419,7 +419,7 @@ contract TimelockControllerTest is Test { ); vm.expectRevert("TimelockController: operation already scheduled"); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -441,7 +441,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -453,13 +453,13 @@ contract TimelockControllerTest is Test { function testProposerCanScheduleOperation() public { bytes32 operationID = _scheduleOperation(PROPOSER_ONE); - assertTrue(timelockController.isOperation(operationID)); + assertTrue(timelockController.is_operation(operationID)); } function testAdminCantScheduleOperation() public { vm.expectRevert("AccessControl: account is missing role"); bytes32 operationID = _scheduleOperation(ADMIN); - assertFalse(timelockController.isOperation(operationID)); + assertFalse(timelockController.is_operation(operationID)); } function _scheduleOperation( @@ -475,7 +475,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.startPrank(proposer); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -483,7 +483,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - operationID = timelockController.hashOperationBatch( + operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -494,12 +494,12 @@ contract TimelockControllerTest is Test { function _laterDelay() internal { vm.prank(address(timelockController)); - timelockController.updateDelay(31 days); + timelockController.update_delay(31 days); } function testReturnsLaterMinDelayForCalls() public { _laterDelay(); - uint256 minDelay = timelockController.getMinDelay(); + uint256 minDelay = timelockController.get_minimum_delay(); assertEq(minDelay, 31 days); } @@ -518,7 +518,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -528,7 +528,7 @@ contract TimelockControllerTest is Test { ); } - function _scheduleBatchedOperation( + function _schedule_batchedOperation( address proposer, uint256 delay ) internal { @@ -542,7 +542,7 @@ contract TimelockControllerTest is Test { payloads[i] = calls[i].data; } - bytes32 batchedOperationID = timelockController.hashOperationBatch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -550,10 +550,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - assertEq(timelockController.isOperation(batchedOperationID), false); + assertEq(timelockController.is_operation(batchedOperationID), false); vm.prank(proposer); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -562,9 +562,9 @@ contract TimelockControllerTest is Test { delay ); - assertEq(timelockController.isOperation(batchedOperationID), true); + assertEq(timelockController.is_operation(batchedOperationID), true); - uint256 operationTimestamp = timelockController.getTimestamp( + uint256 operationTimestamp = timelockController.get_timestamp( batchedOperationID ); assertEq(operationTimestamp, block.timestamp + delay); @@ -572,7 +572,7 @@ contract TimelockControllerTest is Test { function testProposerCanBatchScheduleGreaterEqualToLaterMinDelay() public { _laterDelay(); - _scheduleBatchedOperation(PROPOSER_ONE, 31 days); + _schedule_batchedOperation(PROPOSER_ONE, 31 days); } function testUpdateDelayDoesNotChangeExistingOperationTimestamps() public { @@ -588,7 +588,7 @@ contract TimelockControllerTest is Test { payloads[i] = calls[i].data; } - bytes32 batchedOperationID = timelockController.hashOperationBatch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -597,7 +597,7 @@ contract TimelockControllerTest is Test { ); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -606,16 +606,16 @@ contract TimelockControllerTest is Test { 31 days ); - uint256 operationTimestampBefore = timelockController.getTimestamp( + uint256 operationTimestampBefore = timelockController.get_timestamp( batchedOperationID ); // Set a new delay value vm.prank(address(timelockController)); - timelockController.updateDelay(31 days + 1); + timelockController.update_delay(31 days + 1); // New delay value should only apply on future operations, not existing ones - uint256 operationTimestampAfter = timelockController.getTimestamp( + uint256 operationTimestampAfter = timelockController.get_timestamp( batchedOperationID ); assertEq(operationTimestampAfter, operationTimestampBefore); @@ -628,7 +628,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -649,7 +649,7 @@ contract TimelockControllerTest is Test { } vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -662,7 +662,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("TimelockController: operation is not ready"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -684,7 +684,7 @@ contract TimelockControllerTest is Test { vm.startPrank(PROPOSER_ONE); // Schedule predecessor job - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -692,7 +692,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - bytes32 operationOneID = timelockController.hashOperationBatch( + bytes32 operationOneID = timelockController.hash_operation_batch( targets, values, payloads, @@ -701,7 +701,7 @@ contract TimelockControllerTest is Test { ); // Schedule dependent job - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -713,11 +713,9 @@ contract TimelockControllerTest is Test { // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert( - "TimelockController: predecessor operation is not done" - ); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -739,7 +737,7 @@ contract TimelockControllerTest is Test { vm.startPrank(PROPOSER_ONE); // Prepare predecessor job - bytes32 operationOneID = timelockController.hashOperationBatch( + bytes32 operationOneID = timelockController.hash_operation_batch( targets, values, payloads, @@ -748,7 +746,7 @@ contract TimelockControllerTest is Test { ); // Schedule dependent job - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -760,11 +758,9 @@ contract TimelockControllerTest is Test { // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert( - "TimelockController: predecessor operation is not done" - ); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -788,7 +784,7 @@ contract TimelockControllerTest is Test { // Schedule dependent job vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -799,11 +795,9 @@ contract TimelockControllerTest is Test { // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert( - "TimelockController: predecessor operation is not done" - ); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -824,7 +818,7 @@ contract TimelockControllerTest is Test { // Schedule a job where one target will revert vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -834,9 +828,9 @@ contract TimelockControllerTest is Test { ); vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: underlying transaction reverted"); + vm.expectRevert("Transaction reverted"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -853,7 +847,7 @@ contract TimelockControllerTest is Test { ) = _scheduleSingleBatchedOperation(); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -861,14 +855,14 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT ); - uint256 operationTimestamp = timelockController.getTimestamp( + uint256 operationTimestamp = timelockController.get_timestamp( operationID ); @@ -884,7 +878,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -892,14 +886,14 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT ); - uint256 operationTimestamp = timelockController.getTimestamp( + uint256 operationTimestamp = timelockController.get_timestamp( operationID ); @@ -926,7 +920,7 @@ contract TimelockControllerTest is Test { vm.prank(PROPOSER_ONE); // Schedule batch execution - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -950,7 +944,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -970,7 +964,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -981,7 +975,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY - 2 days); vm.expectRevert("TimelockController: operation is not ready"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1002,7 +996,7 @@ contract TimelockControllerTest is Test { // Schedule predecessor job vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1010,7 +1004,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - bytes32 operationOneID = timelockController.hashOperationBatch( + bytes32 operationOneID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1022,7 +1016,7 @@ contract TimelockControllerTest is Test { // Schedule dependent job vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1033,11 +1027,9 @@ contract TimelockControllerTest is Test { // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert( - "TimelockController: predecessor operation is not done" - ); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1059,7 +1051,7 @@ contract TimelockControllerTest is Test { vm.prank(PROPOSER_ONE); // Schedule predecessor job - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1069,9 +1061,9 @@ contract TimelockControllerTest is Test { ); vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: underlying transaction reverted"); + vm.expectRevert("Transaction reverted"); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1089,7 +1081,7 @@ contract TimelockControllerTest is Test { ) = _executeOperation(num); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1097,14 +1089,14 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT ); - uint256 operationTimestamp = timelockController.getTimestamp( + uint256 operationTimestamp = timelockController.get_timestamp( operationID ); assertEq(operationTimestamp, DONE_TIMESTAMP); @@ -1122,7 +1114,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1130,14 +1122,14 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT ); - uint256 operationTimestamp = timelockController.getTimestamp( + uint256 operationTimestamp = timelockController.get_timestamp( operationID ); assertEq(operationTimestamp, block.timestamp - MIN_DELAY); @@ -1165,7 +1157,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, num); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1196,7 +1188,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1207,7 +1199,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY + 2 days); bytes32 predecessor = NO_PREDECESSOR; bytes32 salt = EMPTY_SALT; - bytes32 id = timelockController.hashOperationBatch( + bytes32 id = timelockController.hash_operation_batch( targets, values, payloads, @@ -1218,7 +1210,7 @@ contract TimelockControllerTest is Test { vm.prank(EXECUTOR_ONE); vm.expectEmit(true, true, true, true); emit CallExecuted(id, 0, targets[0], values[0], payloads[0]); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1244,7 +1236,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1255,14 +1247,14 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY + 1); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1279,7 +1271,7 @@ contract TimelockControllerTest is Test { vm.prank(PROPOSER_ONE); timelockController.cancel(operationID); - assertFalse(timelockController.isOperation(operationID)); + assertFalse(timelockController.is_operation(operationID)); } function testAdminCanCancelOperation() public { @@ -1288,7 +1280,7 @@ contract TimelockControllerTest is Test { vm.expectRevert("AccessControl: account is missing role"); vm.prank(ADMIN); timelockController.cancel(operationID); - assertTrue(timelockController.isOperation(operationID)); + assertTrue(timelockController.is_operation(operationID)); } function _cancelOperation() internal returns (bytes32 operationID) { @@ -1302,7 +1294,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1310,7 +1302,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - operationID = timelockController.hashOperationBatch( + operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1326,8 +1318,8 @@ contract TimelockControllerTest is Test { } function testFalseIfNotAnOperation() public { - bool isOperation = timelockController.isOperation(bytes32("non-op")); - assertEq(isOperation, false); + bool is_operation = timelockController.is_operation(bytes32("non-op")); + assertEq(is_operation, false); } function testTrueIfAnOperation() public { @@ -1341,7 +1333,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1350,7 +1342,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1358,8 +1350,8 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperation = timelockController.isOperation(operationID); - assertEq(isOperation, true); + bool is_operation = timelockController.is_operation(operationID); + assertEq(is_operation, true); } function testTrueIfScheduledOperatonNotYetExecuted() public { @@ -1373,7 +1365,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1382,7 +1374,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1390,10 +1382,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationPending = timelockController.isOperationPending( + bool is_operation_pending = timelockController.is_operation_pending( operationID ); - assertEq(isOperationPending, true); + assertEq(is_operation_pending, true); } function testFalseIfPendingOperationHasBeenExecuted() public { @@ -1407,7 +1399,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1418,7 +1410,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1426,7 +1418,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1434,10 +1426,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationPending = timelockController.isOperationPending( + bool is_operation_pending = timelockController.is_operation_pending( operationID ); - assertEq(isOperationPending, false); + assertEq(is_operation_pending, false); } function testTrueIfOnTheDelayedExecutionTime() public { @@ -1451,7 +1443,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1462,7 +1454,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1470,10 +1462,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationReady = timelockController.isOperationReady( + bool is_operation_ready = timelockController.is_operation_ready( operationID ); - assertEq(isOperationReady, true); + assertEq(is_operation_ready, true); } function testTrueIfAfterTheDelayedExecutionTime() public { @@ -1487,7 +1479,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1498,7 +1490,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY + 1 days); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1506,10 +1498,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationReady = timelockController.isOperationReady( + bool is_operation_ready = timelockController.is_operation_ready( operationID ); - assertEq(isOperationReady, true); + assertEq(is_operation_ready, true); } function testFalseIfBeforeTheDelayedExecutionTime() public { @@ -1523,7 +1515,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1534,7 +1526,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY - 1 days); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1542,10 +1534,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationReady = timelockController.isOperationReady( + bool is_operation_ready = timelockController.is_operation_ready( operationID ); - assertEq(isOperationReady, false); + assertEq(is_operation_ready, false); } function testFalseIfReadyOperationHasBeenExecuted() public { @@ -1559,7 +1551,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1570,7 +1562,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1578,7 +1570,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1586,10 +1578,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationReady = timelockController.isOperationReady( + bool is_operation_ready = timelockController.is_operation_ready( operationID ); - assertEq(isOperationReady, false); + assertEq(is_operation_ready, false); } function testFalseItTheOperationHasNotBeenExecuted() public { @@ -1603,7 +1595,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1612,7 +1604,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1620,8 +1612,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationDone = timelockController.isOperationDone(operationID); - assertEq(isOperationDone, false); + bool is_operation_done = timelockController.is_operation_done( + operationID + ); + assertEq(is_operation_done, false); } function testTrueIfOperationHasBeenExecuted() public { @@ -1635,7 +1629,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1646,7 +1640,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1654,7 +1648,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1662,8 +1656,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool isOperationDone = timelockController.isOperationDone(operationID); - assertEq(isOperationDone, true); + bool is_operation_done = timelockController.is_operation_done( + operationID + ); + assertEq(is_operation_done, true); } function testReturnsTheCorrectTimestampIfTheOperationHasNotBeenExecuted() @@ -1679,7 +1675,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1688,7 +1684,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1696,7 +1692,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - uint256 operationTimestamp = timelockController.getTimestamp( + uint256 operationTimestamp = timelockController.get_timestamp( operationID ); assertEq(operationTimestamp, block.timestamp + MIN_DELAY); @@ -1713,7 +1709,7 @@ contract TimelockControllerTest is Test { payloads[0] = abi.encodeWithSelector(Counter.increment.selector); vm.prank(PROPOSER_ONE); - timelockController.scheduleBatch( + timelockController.schedule_batch( targets, values, payloads, @@ -1724,7 +1720,7 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.executeBatch( + timelockController.execute_batch( targets, values, payloads, @@ -1732,7 +1728,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hashOperationBatch( + bytes32 operationID = timelockController.hash_operation_batch( targets, values, payloads, @@ -1740,7 +1736,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - uint256 operationTimestamp = timelockController.getTimestamp( + uint256 operationTimestamp = timelockController.get_timestamp( operationID ); assertEq(operationTimestamp, DONE_TIMESTAMP); @@ -1776,7 +1772,7 @@ contract Counter { contract TimelockControllerInvariants is Test { VyperDeployer private vyperDeployer = new VyperDeployer(); - TimelockController private timelockController; + ITimelockController private timelockController; TimelockControllerHandler private timelockControllerHandler; address private deployer = address(vyperDeployer); @@ -1796,7 +1792,7 @@ contract TimelockControllerInvariants is Test { executors, address(this) ); - timelockController = TimelockController( + timelockController = ITimelockController( payable( vyperDeployer.deployContract( "src/governance/", @@ -1929,7 +1925,7 @@ contract TimelockControllerInvariants is Test { } contract TimelockControllerHandler is Test { - TimelockController private timelockController; + ITimelockController private timelockController; uint256 private minDelay; address private admin; address private proposer; @@ -1946,7 +1942,7 @@ contract TimelockControllerHandler is Test { uint256[] public cancelled; constructor( - TimelockController timelockController_, + ITimelockController timelockController_, uint256 minDelay_, address[] memory proposer_, address[] memory executor_, diff --git a/test/governance/interfaces/ITimelockController.sol b/test/governance/interfaces/ITimelockController.sol new file mode 100644 index 00000000..f719e8c6 --- /dev/null +++ b/test/governance/interfaces/ITimelockController.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: WTFPL +pragma solidity ^0.8.23; + +interface ITimelockController { + function DEFAULT_ADMIN_ROLE() external view returns (bytes32); + function EXECUTOR_ROLE() external view returns (bytes32); + function PROPOSER_ROLE() external view returns (bytes32); + function TIMELOCK_ADMIN_ROLE() external view returns (bytes32); + function cancel(bytes32 id) external; + function execute( + address target, + uint256 value, + bytes memory data, + bytes32 predecessor, + bytes32 salt + ) external; + function execute_batch( + address[] memory targets, + uint256[] memory values, + bytes[] memory datas, + bytes32 predecessor, + bytes32 salt + ) external; + function get_minimum_delay() external view returns (uint256 duration); + function get_timestamp( + bytes32 id + ) external view returns (uint256 timestamp); + function hasRole( + bytes32 role, + address account + ) external view returns (bool); + function hash_operation_batch( + address[] memory targets, + uint256[] memory values, + bytes[] memory datas, + bytes32 predecessor, + bytes32 salt + ) external pure returns (bytes32 hash); + function is_operation(bytes32 id) external view returns (bool pending); + function is_operation_done(bytes32 id) external view returns (bool done); + function is_operation_pending( + bytes32 id + ) external view returns (bool pending); + function is_operation_ready(bytes32 id) external view returns (bool ready); + function schedule( + address target, + uint256 value, + bytes memory data, + bytes32 predecessor, + bytes32 salt, + uint256 delay + ) external; + function schedule_batch( + address[] memory targets, + uint256[] memory values, + bytes[] memory datas, + bytes32 predecessor, + bytes32 salt, + uint256 delay + ) external; + function update_delay(uint256 newDelay) external; +} From ebc75b9aac32810c9bb5d1c147b728a09ec5294f Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:03:03 +0100 Subject: [PATCH 24/46] =?UTF-8?q?=E2=9C=85=20Add=20value-based=20proposal?= =?UTF-8?q?=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 61 ++++++++++++++++--- .../interfaces/ITimelockController.sol | 7 +++ 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 3a76857f..9f216ad5 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -1741,6 +1741,51 @@ contract TimelockControllerTest is Test { ); assertEq(operationTimestamp, DONE_TIMESTAMP); } + + function testProposeValueProposal() public { + address target = address(counter); + uint256 value = 1 wei; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); + + // Transfer to TimelockController + payable(address(timelockController)).transfer(value); + + vm.prank(PROPOSER_ONE); + timelockController.schedule( + target, + value, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + timelockController.execute( + target, + value, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + + bytes32 operationID = timelockController.hash_operation( + target, + value, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + operationID + ); + assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(address(counter).balance, value); + } } contract Counter { @@ -1751,22 +1796,22 @@ contract Counter { timelock = _timelock; } - function setNumber(uint256 newNumber) public onlyTimelock { + modifier onlyTimelock() { + require(msg.sender == timelock, "Not timelock controller"); + _; + } + + function setNumber(uint256 newNumber) external onlyTimelock { number = newNumber; } - function increment() public onlyTimelock { + function increment() external payable onlyTimelock { number++; } - function mockRevert() public pure { + function mockRevert() external pure { revert("Transaction reverted"); } - - modifier onlyTimelock() { - require(msg.sender == timelock, "Not timelock controller"); - _; - } } contract TimelockControllerInvariants is Test { diff --git a/test/governance/interfaces/ITimelockController.sol b/test/governance/interfaces/ITimelockController.sol index f719e8c6..ba03a67d 100644 --- a/test/governance/interfaces/ITimelockController.sol +++ b/test/governance/interfaces/ITimelockController.sol @@ -29,6 +29,13 @@ interface ITimelockController { bytes32 role, address account ) external view returns (bool); + function hash_operation( + address target, + uint256 value, + bytes memory data, + bytes32 predecessor, + bytes32 salt + ) external pure returns (bytes32 hash); function hash_operation_batch( address[] memory targets, uint256[] memory values, From fd2f78acf999f5ff2336d3c52c818d9f321fdc26 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:18:40 +0100 Subject: [PATCH 25/46] =?UTF-8?q?=F0=9F=94=A7=20Fix=20interface=20data=20p?= =?UTF-8?q?arameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/interfaces/ITimelockController.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/governance/interfaces/ITimelockController.sol b/test/governance/interfaces/ITimelockController.sol index ba03a67d..caeebad2 100644 --- a/test/governance/interfaces/ITimelockController.sol +++ b/test/governance/interfaces/ITimelockController.sol @@ -17,7 +17,7 @@ interface ITimelockController { function execute_batch( address[] memory targets, uint256[] memory values, - bytes[] memory datas, + bytes[] memory data, bytes32 predecessor, bytes32 salt ) external; @@ -39,7 +39,7 @@ interface ITimelockController { function hash_operation_batch( address[] memory targets, uint256[] memory values, - bytes[] memory datas, + bytes[] memory data, bytes32 predecessor, bytes32 salt ) external pure returns (bytes32 hash); @@ -60,7 +60,7 @@ interface ITimelockController { function schedule_batch( address[] memory targets, uint256[] memory values, - bytes[] memory datas, + bytes[] memory data, bytes32 predecessor, bytes32 salt, uint256 delay From 16f8fcf2460148ca9afad1496f62cafb32d30c5f Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Mon, 22 Jan 2024 16:13:37 +0100 Subject: [PATCH 26/46] =?UTF-8?q?=F0=9F=93=96=20data=20->=20payload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 6fff2d48..900ee5cf 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -166,7 +166,7 @@ event CallScheduled: index: indexed(uint256) target: address amount: uint256 - data: Bytes[1_024] + payload: Bytes[1_024] predecessor: bytes32 delay: uint256 @@ -180,7 +180,7 @@ event CallExecuted: index: indexed(uint256) target: address amount: uint256 - data: Bytes[1_024] + payload: Bytes[1_024] # @dev Emitted when new proposal is scheduled with From 8e93c7f4004ee67826c4be696ce915d35eb315ad Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Mon, 22 Jan 2024 16:39:48 +0100 Subject: [PATCH 27/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20Complete=20`ITime?= =?UTF-8?q?lockController`=20Interface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- .../interfaces/ITimelockController.sol | 150 +++++++++++++----- 1 file changed, 109 insertions(+), 41 deletions(-) diff --git a/test/governance/interfaces/ITimelockController.sol b/test/governance/interfaces/ITimelockController.sol index caeebad2..f541949f 100644 --- a/test/governance/interfaces/ITimelockController.sol +++ b/test/governance/interfaces/ITimelockController.sol @@ -1,69 +1,137 @@ // SPDX-License-Identifier: WTFPL pragma solidity ^0.8.23; -interface ITimelockController { - function DEFAULT_ADMIN_ROLE() external view returns (bytes32); - function EXECUTOR_ROLE() external view returns (bytes32); - function PROPOSER_ROLE() external view returns (bytes32); - function TIMELOCK_ADMIN_ROLE() external view returns (bytes32); - function cancel(bytes32 id) external; - function execute( +import {IERC721Receiver} from "openzeppelin/token/ERC721/IERC721Receiver.sol"; +import {IERC1155Receiver} from "openzeppelin/token/ERC1155/IERC1155Receiver.sol"; +import {IAccessControl} from "openzeppelin/access/IAccessControl.sol"; + +interface ITimelockController is + IERC721Receiver, + IERC1155Receiver, + IAccessControl +{ + enum OperationState { + Unset, + Waiting, + Ready, + Done + } + + event CallScheduled( + bytes32 indexed id, + uint256 indexed index, address target, - uint256 value, - bytes memory data, + uint256 amount, + bytes payload, bytes32 predecessor, - bytes32 salt - ) external; - function execute_batch( - address[] memory targets, - uint256[] memory values, - bytes[] memory data, - bytes32 predecessor, - bytes32 salt - ) external; - function get_minimum_delay() external view returns (uint256 duration); - function get_timestamp( + uint256 delay + ); + + event CallExecuted( + bytes32 indexed id, + uint256 indexed index, + address target, + uint256 amount, + bytes payload + ); + + event CallSalt(bytes32 indexed id, bytes32 salt); + + event Cancelled(bytes32 indexed id); + + event MinimumDelayChange(uint256 oldDuration, uint256 newDuration); + + function DEFAULT_ADMIN_ROLE() external pure returns (bytes32); + + function PROPOSER_ROLE() external pure returns (bytes32); + + function EXECUTOR_ROLE() external pure returns (bytes32); + + function CANCELLER_ROLE() external pure returns (bytes32); + + function IERC721_TOKENRECEIVER_SELECTOR() external pure returns (bytes4); + + function IERC1155_TOKENRECEIVER_SINGLE_SELECTOR() + external + pure + returns (bytes4); + + function IERC1155_TOKENRECEIVER_BATCH_SELECTOR() + external + pure + returns (bytes4); + + receive() external payable; + + function get_timestamp(bytes32 id) external view returns (uint256); + + function get_minimum_delay() external view returns (uint256); + + function is_operation(bytes32 id) external view returns (bool); + + function is_operation_pending(bytes32 id) external view returns (bool); + + function is_operation_ready(bytes32 id) external view returns (bool); + + function is_operation_done(bytes32 id) external view returns (bool); + + function get_operation_state( bytes32 id - ) external view returns (uint256 timestamp); - function hasRole( - bytes32 role, - address account - ) external view returns (bool); + ) external view returns (OperationState); + function hash_operation( address target, - uint256 value, - bytes memory data, + uint256 amount, + bytes calldata payload, bytes32 predecessor, bytes32 salt ) external pure returns (bytes32 hash); + function hash_operation_batch( - address[] memory targets, - uint256[] memory values, - bytes[] memory data, + address[] calldata targets, + uint256[] calldata amounts, + bytes[] calldata payloads, bytes32 predecessor, bytes32 salt ) external pure returns (bytes32 hash); - function is_operation(bytes32 id) external view returns (bool pending); - function is_operation_done(bytes32 id) external view returns (bool done); - function is_operation_pending( - bytes32 id - ) external view returns (bool pending); - function is_operation_ready(bytes32 id) external view returns (bool ready); + function schedule( address target, - uint256 value, - bytes memory data, + uint256 amount, + bytes calldata payload, bytes32 predecessor, bytes32 salt, uint256 delay ) external; + function schedule_batch( - address[] memory targets, - uint256[] memory values, - bytes[] memory data, + address[] calldata targets, + uint256[] calldata amounts, + bytes[] calldata payloads, bytes32 predecessor, bytes32 salt, uint256 delay ) external; + + function cancel(bytes32 id) external; + + function execute( + address target, + uint256 amount, + bytes calldata payload, + bytes32 predecessor, + bytes32 salt + ) external payable; + + function execute_batch( + address[] calldata targets, + uint256[] calldata amounts, + bytes[] calldata payloads, + bytes32 predecessor, + bytes32 salt + ) external payable; + function update_delay(uint256 newDelay) external; + + function set_role_admin(bytes32 role, bytes32 adminRole) external; } From f3d79674a1cf6993c7d79c0604c7aec8e0ad4c3d Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Mon, 22 Jan 2024 20:57:36 +0100 Subject: [PATCH 28/46] =?UTF-8?q?=F0=9F=91=B7=20Fix=20Glob=20Pattern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4201955d..cb6b7406 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "url": "https://github.com/pcaversaccio/snekmate/issues" }, "scripts": { - "prettier:check": "npx prettier -c **/*.{md,sol,js,json,yml,yaml}", - "prettier:fix": "npx prettier -w **/*.{md,sol,js,json,yml,yaml}", + "prettier:check": "npx prettier -c '**/*.{md,sol,js,json,yml,yaml}'", + "prettier:fix": "npx prettier -w '**/*.{md,sol,js,json,yml,yaml}'", "solhint:check": "npx solhint '**/*.sol'", "solhint:fix": "npx solhint '**/*.sol' --fix", "lint:check": "pnpm prettier:check && pnpm solhint:check && npx eslint --ext .js .", From c7ef2522f423974eb1eed7e8a060fa48c2289b2f Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Tue, 23 Jan 2024 11:31:48 +0100 Subject: [PATCH 29/46] =?UTF-8?q?=F0=9F=91=B7=20Fix=20Glob=20Pattern=20in?= =?UTF-8?q?=20`npm`=20Scripts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index cb6b7406..8bcbea38 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,10 @@ "url": "https://github.com/pcaversaccio/snekmate/issues" }, "scripts": { - "prettier:check": "npx prettier -c '**/*.{md,sol,js,json,yml,yaml}'", - "prettier:fix": "npx prettier -w '**/*.{md,sol,js,json,yml,yaml}'", - "solhint:check": "npx solhint '**/*.sol'", - "solhint:fix": "npx solhint '**/*.sol' --fix", + "prettier:check": "npx prettier -c \"**/*.{md,sol,js,json,yml,yaml}\"", + "prettier:fix": "npx prettier -w \"**/*.{md,sol,js,json,yml,yaml}\"", + "solhint:check": "npx solhint \"**/*.sol\"", + "solhint:fix": "npx solhint \"**/*.sol\" --fix", "lint:check": "pnpm prettier:check && pnpm solhint:check && npx eslint --ext .js .", "lint:fix": "pnpm prettier:fix && pnpm solhint:fix && npx eslint --ext .js . --fix" }, From abe35d4789d0268cf27ccf9d35f64762c0154caf Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Tue, 23 Jan 2024 16:03:46 +0100 Subject: [PATCH 30/46] =?UTF-8?q?=E2=9C=85=20Add=20event=20emitted=20check?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 1051 +++++++++++++++------- 1 file changed, 748 insertions(+), 303 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 9f216ad5..9d262e87 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -169,8 +169,6 @@ contract TimelockControllerTest is Test { PROPOSERS ); assertEq(timelockController.get_minimum_delay(), MIN_DELAY); - - // TODO: Add event emit checks. } function testHashesBatchedOperationsCorrectly() public { @@ -206,8 +204,6 @@ contract TimelockControllerTest is Test { assertEq(hashedOperation, expectedHash); } - event MinDelayChange(uint256 oldDuration, uint256 newDuration); - function testRevertWhenNotTimelock() public { vm.expectRevert("TimelockController: caller must be timelock"); vm.prank(STRANGER); @@ -222,23 +218,46 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bytes32 predecessor = NO_PREDECESSOR; - bytes32 salt = EMPTY_SALT; + bytes32 id = timelockController.hash_operation( + target, + value, + data, + NO_PREDECESSOR, + EMPTY_SALT + ); vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.CallScheduled( + id, + 0, + target, + value, + data, + NO_PREDECESSOR, + MIN_DELAY + ); timelockController.schedule( target, value, data, - predecessor, - salt, + NO_PREDECESSOR, + EMPTY_SALT, MIN_DELAY ); vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.execute(target, value, data, predecessor, salt); + vm.expectEmit(); + emit ITimelockController.CallExecuted(id, 0, target, value, data); + timelockController.execute( + target, + value, + data, + NO_PREDECESSOR, + EMPTY_SALT + ); uint256 minDelay = timelockController.get_minimum_delay(); assertEq(minDelay, 2 days); @@ -252,17 +271,14 @@ contract TimelockControllerTest is Test { 0 ); - bytes32 predecessor = NO_PREDECESSOR; - bytes32 salt = EMPTY_SALT; - vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); timelockController.schedule( target, value, data, - predecessor, - salt, + NO_PREDECESSOR, + EMPTY_SALT, MIN_DELAY - 1 ); } @@ -278,10 +294,25 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bytes32 predecessor = NO_PREDECESSOR; - bytes32 salt = EMPTY_SALT; + bytes32 id = timelockController.hash_operation( + target, + value, + data, + NO_PREDECESSOR, + EMPTY_SALT + ); vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.CallScheduled( + id, + 0, + target, + value, + data, + NO_PREDECESSOR, + 1 + ); timelockController.schedule( target, value, @@ -294,7 +325,15 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + 1); vm.prank(EXECUTOR_ONE); - timelockController.execute(target, value, data, predecessor, salt); + vm.expectEmit(); + emit ITimelockController.CallExecuted(id, 0, target, value, data); + timelockController.execute( + target, + value, + data, + NO_PREDECESSOR, + EMPTY_SALT + ); uint256 minDelay = timelockController.get_minimum_delay(); assertEq(minDelay, MIN_DELAY); @@ -315,46 +354,9 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - } - - function _schedule_batchedOperation() - internal - view - returns ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) - { - targets = new address[](calls.length); - values = new uint256[](calls.length); - payloads = new bytes[](calls.length); - - for (uint256 i = 0; i < calls.length; ++i) { - targets[i] = calls[i].target; - values[i] = calls[i].value; - payloads[i] = calls[i].data; - } - } - - function testProposerCanBatchSchedule() public { - ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) = _schedule_batchedOperation(); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - assertEq(timelockController.is_operation(batchedOperationID), false); - vm.prank(PROPOSER_ONE); + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); timelockController.schedule_batch( targets, values, @@ -363,16 +365,18 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - - assertEq(timelockController.is_operation(batchedOperationID), true); } - function testAdminCantBatchSchedule() public { - ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) = _schedule_batchedOperation(); + function testProposerCanBatchSchedule() public { + address[] memory targets = new address[](calls.length); + uint256[] memory values = new uint256[](calls.length); + bytes[] memory payloads = new bytes[](calls.length); + + for (uint256 i = 0; i < calls.length; ++i) { + targets[i] = calls[i].target; + values[i] = calls[i].value; + payloads[i] = calls[i].data; + } bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -384,8 +388,19 @@ contract TimelockControllerTest is Test { assertEq(timelockController.is_operation(batchedOperationID), false); - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -395,7 +410,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - assertEq(timelockController.is_operation(batchedOperationID), false); + assertEq(timelockController.is_operation(batchedOperationID), true); } function testRevertWhenScheduleIfOperationScheduled() public { @@ -408,7 +423,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -451,60 +486,27 @@ contract TimelockControllerTest is Test { ); } - function testProposerCanScheduleOperation() public { - bytes32 operationID = _scheduleOperation(PROPOSER_ONE); - assertTrue(timelockController.is_operation(operationID)); - } - - function testAdminCantScheduleOperation() public { - vm.expectRevert("AccessControl: account is missing role"); - bytes32 operationID = _scheduleOperation(ADMIN); - assertFalse(timelockController.is_operation(operationID)); - } - - function _scheduleOperation( - address proposer - ) internal returns (bytes32 operationID) { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - vm.startPrank(proposer); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT + function _laterDelay(uint256 newMinDelay) internal { + vm.startPrank(address(timelockController)); + vm.expectEmit(); + emit ITimelockController.MinimumDelayChange( + timelockController.get_minimum_delay(), + newMinDelay ); - } - - function _laterDelay() internal { - vm.prank(address(timelockController)); - timelockController.update_delay(31 days); + timelockController.update_delay(newMinDelay); + vm.stopPrank(); } function testReturnsLaterMinDelayForCalls() public { - _laterDelay(); + uint256 newMinDelay = 31 days; + _laterDelay(newMinDelay); uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, 31 days); + assertEq(minDelay, newMinDelay); } function testRevertWhenLaterDelayTooLow() public { - _laterDelay(); + uint256 newMinDelay = 31 days; + _laterDelay(newMinDelay); address[] memory targets = new address[](calls.length); uint256[] memory values = new uint256[](calls.length); @@ -524,14 +526,14 @@ contract TimelockControllerTest is Test { payloads, NO_PREDECESSOR, EMPTY_SALT, - 31 days - 1 + newMinDelay - 1 ); } - function _schedule_batchedOperation( - address proposer, - uint256 delay - ) internal { + function testProposerCanBatchScheduleGreaterEqualToLaterMinDelay() public { + uint256 newMinDelay = 31 days; + _laterDelay(newMinDelay); + address[] memory targets = new address[](calls.length); uint256[] memory values = new uint256[](calls.length); bytes[] memory payloads = new bytes[](calls.length); @@ -552,14 +554,26 @@ contract TimelockControllerTest is Test { assertEq(timelockController.is_operation(batchedOperationID), false); - vm.prank(proposer); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + newMinDelay + ); + } timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, - delay + newMinDelay ); assertEq(timelockController.is_operation(batchedOperationID), true); @@ -567,16 +581,12 @@ contract TimelockControllerTest is Test { uint256 operationTimestamp = timelockController.get_timestamp( batchedOperationID ); - assertEq(operationTimestamp, block.timestamp + delay); - } - - function testProposerCanBatchScheduleGreaterEqualToLaterMinDelay() public { - _laterDelay(); - _schedule_batchedOperation(PROPOSER_ONE, 31 days); + assertEq(operationTimestamp, block.timestamp + newMinDelay); } function testUpdateDelayDoesNotChangeExistingOperationTimestamps() public { - _laterDelay(); + uint256 newMinDelay = 31 days; + _laterDelay(newMinDelay); address[] memory targets = new address[](calls.length); uint256[] memory values = new uint256[](calls.length); @@ -597,13 +607,25 @@ contract TimelockControllerTest is Test { ); vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + newMinDelay + ); + } timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT, - 31 days + newMinDelay ); uint256 operationTimestampBefore = timelockController.get_timestamp( @@ -612,7 +634,7 @@ contract TimelockControllerTest is Test { // Set a new delay value vm.prank(address(timelockController)); - timelockController.update_delay(31 days + 1); + timelockController.update_delay(newMinDelay + 1); // New delay value should only apply on future operations, not existing ones uint256 operationTimestampAfter = timelockController.get_timestamp( @@ -648,7 +670,27 @@ contract TimelockControllerTest is Test { payloads[i] = calls[i].data; } + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -681,9 +723,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.startPrank(PROPOSER_ONE); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // Schedule predecessor job + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -692,20 +752,33 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - bytes32 operationOneID = timelockController.hash_operation_batch( + + bytes32 batchedOperationID2 = timelockController.hash_operation_batch( targets, values, payloads, - NO_PREDECESSOR, + batchedOperationID, EMPTY_SALT ); // Schedule dependent job + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID2, + i, + targets[i], + values[i], + payloads[i], + batchedOperationID, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, payloads, - operationOneID, + batchedOperationID, EMPTY_SALT, MIN_DELAY ); @@ -719,7 +792,7 @@ contract TimelockControllerTest is Test { targets, values, payloads, - operationOneID, + batchedOperationID, EMPTY_SALT ); } @@ -745,7 +818,27 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); + bytes32 operationOneID2 = timelockController.hash_operation_batch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT + ); + // Schedule dependent job + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationOneID2, + i, + targets[i], + values[i], + payloads[i], + operationOneID, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -782,8 +875,28 @@ contract TimelockControllerTest is Test { // Prepare invalid predecessor bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + invalidPredecessor, + EMPTY_SALT + ); + // Schedule dependent job vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + invalidPredecessor, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -816,8 +929,28 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + // Schedule a job where one target will revert vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -846,7 +979,25 @@ contract TimelockControllerTest is Test { bytes[] memory payloads ) = _scheduleSingleBatchedOperation(); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -917,9 +1068,28 @@ contract TimelockControllerTest is Test { payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); // Schedule batch execution + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -963,17 +1133,37 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - vm.warp(block.timestamp + MIN_DELAY - 2 days); - vm.expectRevert("TimelockController: operation is not ready"); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.warp(block.timestamp + MIN_DELAY - 2 days); + vm.expectRevert("TimelockController: operation is not ready"); vm.prank(EXECUTOR_ONE); timelockController.execute_batch( targets, @@ -994,22 +1184,35 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // Schedule predecessor job - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - bytes32 operationOneID = timelockController.hash_operation_batch( + + // Schedule predecessor job + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); @@ -1020,7 +1223,7 @@ contract TimelockControllerTest is Test { targets, values, payloads, - operationOneID, + batchedOperationID, EMPTY_SALT, MIN_DELAY ); @@ -1033,7 +1236,7 @@ contract TimelockControllerTest is Test { targets, values, payloads, - operationOneID, + batchedOperationID, EMPTY_SALT ); } @@ -1048,9 +1251,28 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); - vm.prank(PROPOSER_ONE); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); // Schedule predecessor job + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1080,7 +1302,25 @@ contract TimelockControllerTest is Test { bytes[] memory payloads ) = _executeOperation(num); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -1156,38 +1396,27 @@ contract TimelockControllerTest is Test { payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, num); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - vm.warp(block.timestamp + MIN_DELAY + 2 days); - } - - event CallExecuted( - bytes32 indexed id, - uint256 indexed index, - address target, - uint256 value, - bytes data - ); - - function testEmitsEvent() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1196,27 +1425,8 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY + 2 days); - bytes32 predecessor = NO_PREDECESSOR; - bytes32 salt = EMPTY_SALT; - bytes32 id = timelockController.hash_operation_batch( - targets, - values, - payloads, - predecessor, - salt - ); - vm.prank(EXECUTOR_ONE); - vm.expectEmit(true, true, true, true); - emit CallExecuted(id, 0, targets[0], values[0], payloads[0]); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); + vm.warp(block.timestamp + MIN_DELAY + 2 days); } function testRevertWhenNonCanceller() public { @@ -1235,7 +1445,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1247,6 +1477,16 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY + 1); vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -1254,27 +1494,22 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); vm.prank(PROPOSER_ONE); vm.expectRevert("TimelockController: operation cannot be cancelled"); - timelockController.cancel(operationID); + timelockController.cancel(batchedOperationID); } function testCancellerCanCancelOperation() public { bytes32 operationID = _cancelOperation(); vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.Cancelled(operationID); timelockController.cancel(operationID); assertFalse(timelockController.is_operation(operationID)); } - function testAdminCanCancelOperation() public { + function testAdminCantCancelOperation() public { bytes32 operationID = _cancelOperation(); vm.expectRevert("AccessControl: account is missing role"); @@ -1293,7 +1528,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1332,25 +1587,37 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); - bool is_operation = timelockController.is_operation(operationID); + bool is_operation = timelockController.is_operation(batchedOperationID); assertEq(is_operation, true); } @@ -1364,26 +1631,38 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); bool is_operation_pending = timelockController.is_operation_pending( - operationID + batchedOperationID ); assertEq(is_operation_pending, true); } @@ -1398,7 +1677,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1410,6 +1709,16 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -1418,16 +1727,8 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - bool is_operation_pending = timelockController.is_operation_pending( - operationID + batchedOperationID ); assertEq(is_operation_pending, false); } @@ -1442,28 +1743,40 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - vm.warp(block.timestamp + MIN_DELAY); - - bytes32 operationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); + vm.warp(block.timestamp + MIN_DELAY); + bool is_operation_ready = timelockController.is_operation_ready( - operationID + batchedOperationID ); assertEq(is_operation_ready, true); } @@ -1478,28 +1791,40 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - vm.warp(block.timestamp + MIN_DELAY + 1 days); - - bytes32 operationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); + vm.warp(block.timestamp + MIN_DELAY + 1 days); + bool is_operation_ready = timelockController.is_operation_ready( - operationID + batchedOperationID ); assertEq(is_operation_ready, true); } @@ -1514,28 +1839,40 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - vm.warp(block.timestamp + MIN_DELAY - 1 days); - - bytes32 operationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); + vm.warp(block.timestamp + MIN_DELAY - 1 days); + bool is_operation_ready = timelockController.is_operation_ready( - operationID + batchedOperationID ); assertEq(is_operation_ready, false); } @@ -1550,7 +1887,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1562,6 +1919,16 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -1570,16 +1937,8 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - bool is_operation_ready = timelockController.is_operation_ready( - operationID + batchedOperationID ); assertEq(is_operation_ready, false); } @@ -1594,26 +1953,38 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); bool is_operation_done = timelockController.is_operation_done( - operationID + batchedOperationID ); assertEq(is_operation_done, false); } @@ -1628,7 +1999,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1640,6 +2031,16 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -1648,16 +2049,8 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - bool is_operation_done = timelockController.is_operation_done( - operationID + batchedOperationID ); assertEq(is_operation_done, true); } @@ -1674,26 +2067,38 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); uint256 operationTimestamp = timelockController.get_timestamp( - operationID + batchedOperationID ); assertEq(operationTimestamp, block.timestamp + MIN_DELAY); } @@ -1708,7 +2113,27 @@ contract TimelockControllerTest is Test { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } timelockController.schedule_batch( targets, values, @@ -1720,6 +2145,16 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -1728,16 +2163,8 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - uint256 operationTimestamp = timelockController.get_timestamp( - operationID + batchedOperationID ); assertEq(operationTimestamp, DONE_TIMESTAMP); } @@ -1752,7 +2179,25 @@ contract TimelockControllerTest is Test { // Transfer to TimelockController payable(address(timelockController)).transfer(value); + bytes32 operationID = timelockController.hash_operation( + target, + value, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + value, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); timelockController.schedule( target, value, @@ -1764,15 +2209,15 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - timelockController.execute( + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, target, value, - payload, - NO_PREDECESSOR, - EMPTY_SALT + payload ); - - bytes32 operationID = timelockController.hash_operation( + timelockController.execute( target, value, payload, From 473914e6fd66c03edecf25633ed177647fdf553e Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Tue, 23 Jan 2024 16:28:53 +0100 Subject: [PATCH 31/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20`constant`=20f?= =?UTF-8?q?or=20`DynArray`=20Bound?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/governance/TimelockController.vy | 32 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/governance/TimelockController.vy b/src/governance/TimelockController.vy index 900ee5cf..0e904e45 100644 --- a/src/governance/TimelockController.vy +++ b/src/governance/TimelockController.vy @@ -121,6 +121,10 @@ _SUPPORTED_INTERFACES: constant(bytes4[3]) = [ _DONE_TIMESTAMP: constant(uint256) = 1 +# @dev Stores the 1-byte upper bound for the dynamic arrays. +_DYNARRAY_BOUND: constant(uint8) = max_value(uint8) + + # @dev The possible states of a proposal. # @notice Enums are treated differently in Vyper and # Solidity. The members are represented by `uint256` @@ -237,7 +241,7 @@ event RoleRevoked: @external @payable -def __init__(minimum_delay_: uint256, proposers_: DynArray[address, 128], executors_: DynArray[address, 128], admin_: address): +def __init__(minimum_delay_: uint256, proposers_: DynArray[address, _DYNARRAY_BOUND], executors_: DynArray[address, _DYNARRAY_BOUND], admin_: address): """ @dev Initialises the contract with the following parameters: - `minimum_delay_`: The initial minimum delay in seconds @@ -396,8 +400,8 @@ def hash_operation(target: address, amount: uint256, payload: Bytes[1_024], pred @external @pure -def hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, - salt: bytes32) -> bytes32: +def hash_operation_batch(targets: DynArray[address, _DYNARRAY_BOUND], amounts: DynArray[uint256, _DYNARRAY_BOUND], payloads: DynArray[Bytes[1_024], _DYNARRAY_BOUND], + predecessor: bytes32, salt: bytes32) -> bytes32: """ @dev Returns the identifier of an operation containing a batch of transactions. @@ -440,8 +444,8 @@ def schedule(target: address, amount: uint256, payload: Bytes[1_024], predecesso @external -def schedule_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, - salt: bytes32, delay: uint256): +def schedule_batch(targets: DynArray[address, _DYNARRAY_BOUND], amounts: DynArray[uint256, _DYNARRAY_BOUND], payloads: DynArray[Bytes[1_024], _DYNARRAY_BOUND], + predecessor: bytes32, salt: bytes32, delay: uint256): """ @dev Schedules an operation containing a batch of transactions. Emits one `CallScheduled` event per transaction in the @@ -467,8 +471,9 @@ def schedule_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 1 for target in targets: log CallScheduled(id, idx, target, amounts[idx], payloads[idx], predecessor, delay) # The following line cannot overflow because we have - # limited the dynamic array `targets` by the maximum - # value of `128`. + # limited the dynamic array `targets` by the `constant` + # parameter `_DYNARRAY_BOUND`, which is bounded by the + # maximum value of `uint8`. idx = unsafe_add(idx, 1) if (salt != empty(bytes32)): log CallSalt(id, salt) @@ -517,8 +522,8 @@ def execute(target: address, amount: uint256, payload: Bytes[1_024], predecessor @external @payable -def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, - salt: bytes32): +def execute_batch(targets: DynArray[address, _DYNARRAY_BOUND], amounts: DynArray[uint256, _DYNARRAY_BOUND], payloads: DynArray[Bytes[1_024], _DYNARRAY_BOUND], + predecessor: bytes32, salt: bytes32): """ @dev Executes a ready operation containing a batch of transactions. Emits one `CallExecuted` event per transaction in the batch. @@ -546,8 +551,9 @@ def execute_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 12 self._execute(target, amounts[idx], payloads[idx]) log CallExecuted(id, idx, target, amounts[idx], payloads[idx]) # The following line cannot overflow because we have - # limited the dynamic array `targets` by the maximum - # value of `128`. + # limited the dynamic array `targets` by the `constant` + # parameter `_DYNARRAY_BOUND`, which is bounded by the + # maximum value of `uint8`. idx = unsafe_add(idx, 1) self._after_call(id) @@ -782,8 +788,8 @@ def _hash_operation(target: address, amount: uint256, payload: Bytes[1_024], pre @internal @pure -def _hash_operation_batch(targets: DynArray[address, 128], amounts: DynArray[uint256, 128], payloads: DynArray[Bytes[1_024], 128], predecessor: bytes32, - salt: bytes32) -> bytes32: +def _hash_operation_batch(targets: DynArray[address, _DYNARRAY_BOUND], amounts: DynArray[uint256, _DYNARRAY_BOUND], payloads: DynArray[Bytes[1_024], _DYNARRAY_BOUND], + predecessor: bytes32, salt: bytes32) -> bytes32: """ @dev Returns the identifier of an operation containing a batch of transactions. From f05ffab81b4729a5fd38d143bac8b65d140efff7 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Tue, 23 Jan 2024 16:33:02 +0100 Subject: [PATCH 32/46] =?UTF-8?q?=F0=9F=93=96=20Correct=20Label=20in=20`CH?= =?UTF-8?q?ANGELOG`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a3b56a1..be8ef13f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### 💥 New Features -- **Extensions** +- **Governance** - [`TimelockController`](https://github.com/pcaversaccio/snekmate/blob/v0.0.5/src/governance/TimelockController.vy): A multi-role-based timelock controller reference implementation. ([#195](https://github.com/pcaversaccio/snekmate/pull/195)) ### ♻️ Refactoring From c8a77c18526545521f16f23792a6ab539e771aaa Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Tue, 23 Jan 2024 16:37:29 +0100 Subject: [PATCH 33/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20amend=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- src/utils/Create2Address.vy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/Create2Address.vy b/src/utils/Create2Address.vy index 15afc21e..4effe643 100644 --- a/src/utils/Create2Address.vy +++ b/src/utils/Create2Address.vy @@ -12,7 +12,7 @@ """ -# @dev The `CREATE2` offset constant used to prevent +# @dev The 1-byte `CREATE2` offset constant used to prevent # collisions with addresses created using the traditional # `keccak256(rlp([sender, nonce]))` formula. _COLLISION_OFFSET: constant(bytes1) = 0xFF From dae2b5f6be06f1fdfb361fb0f7d745d573d0df6b Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:45:47 +0100 Subject: [PATCH 34/46] =?UTF-8?q?=E2=9C=85=20Add=20roles=20for=20permissio?= =?UTF-8?q?ns=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 1482 +++++++++++++--------- 1 file changed, 848 insertions(+), 634 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 9d262e87..88430c83 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -41,6 +41,10 @@ contract TimelockControllerTest is Test { address private deployer = address(vyperDeployer); + /*////////////////////////////////////////////////////////////// + SET UP + //////////////////////////////////////////////////////////////*/ + function setUp() public { PROPOSERS[0] = PROPOSER_ONE; PROPOSERS[1] = PROPOSER_TWO; @@ -85,16 +89,6 @@ contract TimelockControllerTest is Test { ); } - function checkRoleNotSetForAddresses( - ITimelockController timelock, - bytes32 role, - address[2] storage addresses - ) internal { - for (uint256 i = 0; i < addresses.length; ++i) { - assertFalse(timelock.hasRole(role, addresses[i])); - } - } - function testInitialSetup() public { assertEq( timelockController.hasRole( @@ -171,98 +165,186 @@ contract TimelockControllerTest is Test { assertEq(timelockController.get_minimum_delay(), MIN_DELAY); } - function testHashesBatchedOperationsCorrectly() public { - address[] memory targets = new address[](2); - targets[0] = address(this); - targets[1] = address(this); + /*////////////////////////////////////////////////////////////// + HELPERS + //////////////////////////////////////////////////////////////*/ - uint256[] memory values = new uint256[](2); - values[0] = 0; - values[1] = 1; + function checkRoleNotSetForAddresses( + ITimelockController timelock, + bytes32 role, + address[2] storage addresses + ) internal { + for (uint256 i = 0; i < addresses.length; ++i) { + assertFalse(timelock.hasRole(role, addresses[i])); + } + } - bytes[] memory payloads = new bytes[](2); - payloads[0] = abi.encodeWithSelector( - this.testHashesBatchedOperationsCorrectly.selector - ); - payloads[1] = abi.encodeWithSelector( - this.testHashesBatchedOperationsCorrectly.selector - ); + function _scheduleSingleBatchedOperation() + internal + returns ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) + { + targets = new address[](1); + targets[0] = address(counter); - bytes32 predecessor = NO_PREDECESSOR; - bytes32 salt = EMPTY_SALT; + values = new uint256[](1); + values[0] = 0; - bytes32 hashedOperation = timelockController.hash_operation_batch( + payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, - predecessor, - salt + NO_PREDECESSOR, + EMPTY_SALT ); - bytes32 expectedHash = keccak256( - abi.encode(targets, values, payloads, predecessor, salt) + + // Schedule batch execution + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY ); - assertEq(hashedOperation, expectedHash); - } - function testRevertWhenNotTimelock() public { - vm.expectRevert("TimelockController: caller must be timelock"); - vm.prank(STRANGER); - timelockController.update_delay(3 days); + vm.warp(block.timestamp + MIN_DELAY); } - function testUpdatesMinDelay() public { - address target = address(timelockController); - uint256 value = 0; - bytes memory data = abi.encodeWithSelector( - timelockController.update_delay.selector, - MIN_DELAY + function _laterDelay(uint256 newMinDelay) internal { + vm.startPrank(address(timelockController)); + vm.expectEmit(); + emit ITimelockController.MinimumDelayChange( + timelockController.get_minimum_delay(), + newMinDelay ); + timelockController.update_delay(newMinDelay); + vm.stopPrank(); + } - bytes32 id = timelockController.hash_operation( - target, - value, - data, + function _executeOperation( + uint256 num + ) + internal + returns ( + address[] memory targets, + uint256[] memory values, + bytes[] memory payloads + ) + { + targets = new address[](1); + targets[0] = address(counter); + + values = new uint256[](1); + values[0] = 0; + + payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, num); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - id, - 0, - target, - value, - data, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - value, - data, + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + } - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted(id, 0, target, value, data); - timelockController.execute( - target, - value, - data, + function _cancelOperation() internal returns (bytes32 operationID) { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, NO_PREDECESSOR, EMPTY_SALT ); - uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, 2 days); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + operationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); } + /*////////////////////////////////////////////////////////////// + OPERATION TESTS + //////////////////////////////////////////////////////////////*/ + function testRevertWhenLessThanMinDelay() public { address target = address(timelockController); uint256 value = 0; @@ -339,170 +421,141 @@ contract TimelockControllerTest is Test { assertEq(minDelay, MIN_DELAY); } - function testRevertWhenNotProposer() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); + function testUpdatesMinDelay() public { + address target = address(timelockController); + uint256 value = 0; + bytes memory data = abi.encodeWithSelector( + timelockController.update_delay.selector, + MIN_DELAY + ); - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.schedule_batch( - targets, - values, - payloads, + bytes32 id = timelockController.hash_operation( + target, + value, + data, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT ); - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.schedule_batch( - targets, - values, - payloads, + vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.CallScheduled( + id, + 0, + target, + value, + data, NO_PREDECESSOR, - EMPTY_SALT, MIN_DELAY ); - } - - function testProposerCanBatchSchedule() public { - address[] memory targets = new address[](calls.length); - uint256[] memory values = new uint256[](calls.length); - bytes[] memory payloads = new bytes[](calls.length); - - for (uint256 i = 0; i < calls.length; ++i) { - targets[i] = calls[i].target; - values[i] = calls[i].value; - payloads[i] = calls[i].data; - } - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - assertEq(timelockController.is_operation(batchedOperationID), false); - - vm.startPrank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + timelockController.schedule( + target, + value, + data, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); - assertEq(timelockController.is_operation(batchedOperationID), true); - } - - function testRevertWhenScheduleIfOperationScheduled() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + vm.warp(block.timestamp + MIN_DELAY); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + vm.prank(EXECUTOR_ONE); + vm.expectEmit(); + emit ITimelockController.CallExecuted(id, 0, target, value, data); + timelockController.execute( + target, + value, + data, NO_PREDECESSOR, EMPTY_SALT ); - vm.startPrank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.expectRevert("TimelockController: operation already scheduled"); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); + uint256 minDelay = timelockController.get_minimum_delay(); + assertEq(minDelay, 2 days); } - function testRevertWhenScheduleIfDelayLessThanMinDelay() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); + /*////////////////////////////////////////////////////////////// + BATCHED OPERATION TESTS + //////////////////////////////////////////////////////////////*/ - uint256[] memory values = new uint256[](1); + function testHashesBatchedOperationsCorrectly() public { + address[] memory targets = new address[](2); + targets[0] = address(this); + targets[1] = address(this); + + uint256[] memory values = new uint256[](2); values[0] = 0; + values[1] = 1; - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + bytes[] memory payloads = new bytes[](2); + payloads[0] = abi.encodeWithSelector( + this.testHashesBatchedOperationsCorrectly.selector + ); + payloads[1] = abi.encodeWithSelector( + this.testHashesBatchedOperationsCorrectly.selector + ); - vm.expectRevert("TimelockController: insufficient delay"); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( + bytes32 predecessor = NO_PREDECESSOR; + bytes32 salt = EMPTY_SALT; + + bytes32 hashedOperation = timelockController.hash_operation_batch( targets, values, payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - 1 + predecessor, + salt ); - } - - function _laterDelay(uint256 newMinDelay) internal { - vm.startPrank(address(timelockController)); - vm.expectEmit(); - emit ITimelockController.MinimumDelayChange( - timelockController.get_minimum_delay(), - newMinDelay + bytes32 expectedHash = keccak256( + abi.encode(targets, values, payloads, predecessor, salt) ); - timelockController.update_delay(newMinDelay); - vm.stopPrank(); + assertEq(hashedOperation, expectedHash); } - function testReturnsLaterMinDelayForCalls() public { - uint256 newMinDelay = 31 days; - _laterDelay(newMinDelay); - uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, newMinDelay); - } + // function testProposerCanBatchSchedule() public { + // address[] memory targets = new address[](calls.length); + // uint256[] memory values = new uint256[](calls.length); + // bytes[] memory payloads = new bytes[](calls.length); + + // for (uint256 i = 0; i < calls.length; ++i) { + // targets[i] = calls[i].target; + // values[i] = calls[i].value; + // payloads[i] = calls[i].data; + // } + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // assertEq(timelockController.is_operation(batchedOperationID), false); + + // vm.startPrank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // assertEq(timelockController.is_operation(batchedOperationID), true); + // } function testRevertWhenLaterDelayTooLow() public { uint256 newMinDelay = 31 days; @@ -530,7 +583,61 @@ contract TimelockControllerTest is Test { ); } - function testProposerCanBatchScheduleGreaterEqualToLaterMinDelay() public { + // function testProposerCanBatchScheduleGreaterEqualToLaterMinDelay() public { + // uint256 newMinDelay = 31 days; + // _laterDelay(newMinDelay); + + // address[] memory targets = new address[](calls.length); + // uint256[] memory values = new uint256[](calls.length); + // bytes[] memory payloads = new bytes[](calls.length); + + // for (uint256 i = 0; i < calls.length; ++i) { + // targets[i] = calls[i].target; + // values[i] = calls[i].value; + // payloads[i] = calls[i].data; + // } + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // assertEq(timelockController.is_operation(batchedOperationID), false); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // newMinDelay + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // newMinDelay + // ); + + // assertEq(timelockController.is_operation(batchedOperationID), true); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, block.timestamp + newMinDelay); + // } + + function testUpdateDelayDoesNotChangeExistingOperationTimestamps() public { uint256 newMinDelay = 31 days; _laterDelay(newMinDelay); @@ -552,8 +659,6 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - assertEq(timelockController.is_operation(batchedOperationID), false); - vm.prank(PROPOSER_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(); @@ -576,27 +681,58 @@ contract TimelockControllerTest is Test { newMinDelay ); - assertEq(timelockController.is_operation(batchedOperationID), true); + uint256 operationTimestampBefore = timelockController.get_timestamp( + batchedOperationID + ); + + // Set a new delay value + vm.prank(address(timelockController)); + timelockController.update_delay(newMinDelay + 1); - uint256 operationTimestamp = timelockController.get_timestamp( + // New delay value should only apply on future operations, not existing ones + uint256 operationTimestampAfter = timelockController.get_timestamp( batchedOperationID ); - assertEq(operationTimestamp, block.timestamp + newMinDelay); + assertEq(operationTimestampAfter, operationTimestampBefore); } - function testUpdateDelayDoesNotChangeExistingOperationTimestamps() public { - uint256 newMinDelay = 31 days; - _laterDelay(newMinDelay); + function testRevertWhenNotProposer() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); - address[] memory targets = new address[](calls.length); - uint256[] memory values = new uint256[](calls.length); - bytes[] memory payloads = new bytes[](calls.length); + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); - for (uint256 i = 0; i < calls.length; ++i) { - targets[i] = calls[i].target; - values[i] = calls[i].value; - payloads[i] = calls[i].data; - } + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + } + + function testRevertWhenScheduleIfOperationScheduled() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -606,7 +742,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - vm.prank(PROPOSER_ONE); + vm.startPrank(PROPOSER_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(); emit ITimelockController.CallScheduled( @@ -616,7 +752,7 @@ contract TimelockControllerTest is Test { values[i], payloads[i], NO_PREDECESSOR, - newMinDelay + MIN_DELAY ); } timelockController.schedule_batch( @@ -625,37 +761,39 @@ contract TimelockControllerTest is Test { payloads, NO_PREDECESSOR, EMPTY_SALT, - newMinDelay + MIN_DELAY ); - uint256 operationTimestampBefore = timelockController.get_timestamp( - batchedOperationID + vm.expectRevert("TimelockController: operation already scheduled"); + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY ); + } - // Set a new delay value - vm.prank(address(timelockController)); - timelockController.update_delay(newMinDelay + 1); + function testRevertWhenScheduleIfDelayLessThanMinDelay() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); - // New delay value should only apply on future operations, not existing ones - uint256 operationTimestampAfter = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestampAfter, operationTimestampBefore); - } + uint256[] memory values = new uint256[](1); + values[0] = 0; - function testRevertWhenNotExecutor() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.execute_batch( + vm.expectRevert("TimelockController: insufficient delay"); + vm.prank(PROPOSER_ONE); + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY - 1 ); } @@ -1020,109 +1158,6 @@ contract TimelockControllerTest is Test { assertEq(operationTimestamp, DONE_TIMESTAMP); } - function testAdminCantBatchExecuteOperation() public { - ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) = _scheduleSingleBatchedOperation(); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - uint256 operationTimestamp = timelockController.get_timestamp( - operationID - ); - - assertEq(operationTimestamp, block.timestamp); - } - - function _scheduleSingleBatchedOperation() - internal - returns ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) - { - targets = new address[](1); - targets[0] = address(counter); - - values = new uint256[](1); - values[0] = 0; - - payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - // Schedule batch execution - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - } - - function testRevertWhenExecutedByNonExecutor() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - function testRevertWhenSingleOperationNotReady() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1294,13 +1329,15 @@ contract TimelockControllerTest is Test { ); } - function testExecutorCanExecuteOperation() public { - uint256 num = 10; - ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) = _executeOperation(num); + function testRevertWhenFinishedOperation() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -1310,50 +1347,40 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - vm.prank(EXECUTOR_ONE); + vm.prank(PROPOSER_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(); - emit ITimelockController.CallExecuted( + emit ITimelockController.CallScheduled( batchedOperationID, i, targets[i], values[i], - payloads[i] + payloads[i], + NO_PREDECESSOR, + MIN_DELAY ); } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bytes32 operationID = timelockController.hash_operation_batch( + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT - ); - uint256 operationTimestamp = timelockController.get_timestamp( - operationID + EMPTY_SALT, + MIN_DELAY ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - uint256 counterNumber = counter.number(); - assertEq(counterNumber, num); - } - function testAdminCantExecuteOperation() public { - uint256 num = 10; - ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) = _executeOperation(num); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); + vm.warp(block.timestamp + MIN_DELAY + 1); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } timelockController.execute_batch( targets, values, @@ -1361,40 +1388,20 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); - - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - uint256 operationTimestamp = timelockController.get_timestamp( - operationID - ); - assertEq(operationTimestamp, block.timestamp - MIN_DELAY); - uint256 counterNumber = counter.number(); - assertEq(counterNumber, 0); + vm.prank(PROPOSER_ONE); + vm.expectRevert("TimelockController: operation cannot be cancelled"); + timelockController.cancel(batchedOperationID); } - function _executeOperation( - uint256 num - ) - internal - returns ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) - { - targets = new address[](1); + function testTrueIfScheduledOperatonNotYetExecuted() public { + address[] memory targets = new address[](1); targets[0] = address(counter); - values = new uint256[](1); + uint256[] memory values = new uint256[](1); values[0] = 0; - payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, num); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -1426,16 +1433,13 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY + 2 days); - } - - function testRevertWhenNonCanceller() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(EXECUTOR_ONE); - timelockController.cancel(EMPTY_SALT); + bool is_operation_pending = timelockController.is_operation_pending( + batchedOperationID + ); + assertEq(is_operation_pending, true); } - function testRevertWhenFinishedOperation() public { + function testFalseIfPendingOperationHasBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1475,7 +1479,7 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY + 1); + vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(); @@ -1494,31 +1498,14 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); - vm.prank(PROPOSER_ONE); - vm.expectRevert("TimelockController: operation cannot be cancelled"); - timelockController.cancel(batchedOperationID); - } - - function testCancellerCanCancelOperation() public { - bytes32 operationID = _cancelOperation(); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.Cancelled(operationID); - timelockController.cancel(operationID); - assertFalse(timelockController.is_operation(operationID)); - } - function testAdminCantCancelOperation() public { - bytes32 operationID = _cancelOperation(); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.cancel(operationID); - assertTrue(timelockController.is_operation(operationID)); + bool is_operation_pending = timelockController.is_operation_pending( + batchedOperationID + ); + assertEq(is_operation_pending, false); } - function _cancelOperation() internal returns (bytes32 operationID) { + function testTrueIfOnTheDelayedExecutionTime() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1557,27 +1544,16 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - function testCanReceiveETH() public { - vm.prank(ADMIN); - payable(address(timelockController)).transfer(0.5 ether); - assertEq(address(timelockController).balance, 0.5 ether); - } + vm.warp(block.timestamp + MIN_DELAY); - function testFalseIfNotAnOperation() public { - bool is_operation = timelockController.is_operation(bytes32("non-op")); - assertEq(is_operation, false); + bool is_operation_ready = timelockController.is_operation_ready( + batchedOperationID + ); + assertEq(is_operation_ready, true); } - function testTrueIfAnOperation() public { + function testTrueIfAfterTheDelayedExecutionTime() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1617,12 +1593,16 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bool is_operation = timelockController.is_operation(batchedOperationID); - assertEq(is_operation, true); - } + vm.warp(block.timestamp + MIN_DELAY + 1 days); - function testTrueIfScheduledOperatonNotYetExecuted() public { - address[] memory targets = new address[](1); + bool is_operation_ready = timelockController.is_operation_ready( + batchedOperationID + ); + assertEq(is_operation_ready, true); + } + + function testFalseIfBeforeTheDelayedExecutionTime() public { + address[] memory targets = new address[](1); targets[0] = address(counter); uint256[] memory values = new uint256[](1); @@ -1661,13 +1641,15 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bool is_operation_pending = timelockController.is_operation_pending( + vm.warp(block.timestamp + MIN_DELAY - 1 days); + + bool is_operation_ready = timelockController.is_operation_ready( batchedOperationID ); - assertEq(is_operation_pending, true); + assertEq(is_operation_ready, false); } - function testFalseIfPendingOperationHasBeenExecuted() public { + function testFalseIfReadyOperationHasBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1727,13 +1709,13 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool is_operation_pending = timelockController.is_operation_pending( + bool is_operation_ready = timelockController.is_operation_ready( batchedOperationID ); - assertEq(is_operation_pending, false); + assertEq(is_operation_ready, false); } - function testTrueIfOnTheDelayedExecutionTime() public { + function testFalseItTheOperationHasNotBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1773,15 +1755,13 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY); - - bool is_operation_ready = timelockController.is_operation_ready( + bool is_operation_done = timelockController.is_operation_done( batchedOperationID ); - assertEq(is_operation_ready, true); + assertEq(is_operation_done, false); } - function testTrueIfAfterTheDelayedExecutionTime() public { + function testTrueIfOperationHasBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1821,15 +1801,35 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY + 1 days); + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bool is_operation_ready = timelockController.is_operation_ready( + bool is_operation_done = timelockController.is_operation_done( batchedOperationID ); - assertEq(is_operation_ready, true); + assertEq(is_operation_done, true); } - function testFalseIfBeforeTheDelayedExecutionTime() public { + function testReturnsTheCorrectTimestampIfTheOperationHasNotBeenExecuted() + public + { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1869,15 +1869,13 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY - 1 days); - - bool is_operation_ready = timelockController.is_operation_ready( + uint256 operationTimestamp = timelockController.get_timestamp( batchedOperationID ); - assertEq(is_operation_ready, false); + assertEq(operationTimestamp, block.timestamp + MIN_DELAY); } - function testFalseIfReadyOperationHasBeenExecuted() public { + function testReturnsOneIfOperationHasBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1937,13 +1935,35 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool is_operation_ready = timelockController.is_operation_ready( + uint256 operationTimestamp = timelockController.get_timestamp( batchedOperationID ); - assertEq(is_operation_ready, false); + assertEq(operationTimestamp, DONE_TIMESTAMP); } - function testFalseItTheOperationHasNotBeenExecuted() public { + /*////////////////////////////////////////////////////////////// + SANITY CHECKS TESTS + //////////////////////////////////////////////////////////////*/ + + function testReturnsLaterMinDelayForCalls() public { + uint256 newMinDelay = 31 days; + _laterDelay(newMinDelay); + uint256 minDelay = timelockController.get_minimum_delay(); + assertEq(minDelay, newMinDelay); + } + + function testCanReceiveETH() public { + vm.prank(ADMIN); + payable(address(timelockController)).transfer(0.5 ether); + assertEq(address(timelockController).balance, 0.5 ether); + } + + function testFalseIfNotAnOperation() public { + bool is_operation = timelockController.is_operation(bytes32("non-op")); + assertEq(is_operation, false); + } + + function testTrueIfAnOperation() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1983,43 +2003,96 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bool is_operation_done = timelockController.is_operation_done( - batchedOperationID - ); - assertEq(is_operation_done, false); + bool is_operation = timelockController.is_operation(batchedOperationID); + assertEq(is_operation, true); } - function testTrueIfOperationHasBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; + function testProposeValueProposal() public { + address target = address(counter); + uint256 value = 1 wei; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + // Transfer to TimelockController + payable(address(timelockController)).transfer(value); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + value, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + value, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + value, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, + target, + value, + payload + ); + timelockController.execute( + target, + value, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + operationID + ); + assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(address(counter).balance, value); + } + + // TODO Add supportsInterface checks for + // TODO: Add NFTs tests + + /*////////////////////////////////////////////////////////////// + PERMISSION TESTS + //////////////////////////////////////////////////////////////*/ + + // Timelock + function testRevertWhenNotTimelock() public { + vm.expectRevert("TimelockController: caller must be timelock"); + vm.prank(STRANGER); + timelockController.update_delay(3 days); + } + + // Admin + + function testAdminCantBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); timelockController.schedule_batch( targets, values, @@ -2028,19 +2101,28 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); + } - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } + function testAdminCantSchedule() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.schedule( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + } + + function testAdminCantBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); timelockController.execute_batch( targets, values, @@ -2048,92 +2130,143 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); + } - bool is_operation_done = timelockController.is_operation_done( - batchedOperationID + function testAdminCantExecute() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.execute( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, + EMPTY_SALT ); - assertEq(is_operation_done, true); } - function testReturnsTheCorrectTimestampIfTheOperationHasNotBeenExecuted() - public - { - address[] memory targets = new address[](1); - targets[0] = address(counter); + function testAdminCantCancel() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(ADMIN); + timelockController.cancel(EMPTY_SALT); + } - uint256[] memory values = new uint256[](1); - values[0] = 0; + // Proposer - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + function testProposerCanBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); - bytes32 batchedOperationID = timelockController.hash_operation_batch( + vm.prank(PROPOSER_ONE); + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } + vm.prank(PROPOSER_TWO); timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, + bytes32("1"), + MIN_DELAY + ); + } + + function testProposerCanSchedule() public { + vm.prank(PROPOSER_ONE); + timelockController.schedule( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID + vm.prank(PROPOSER_TWO); + timelockController.schedule( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, + bytes32("1"), + MIN_DELAY ); - assertEq(operationTimestamp, block.timestamp + MIN_DELAY); } - function testReturnsOneIfOperationHasBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; + function testProposerCantBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_TWO); + timelockController.execute_batch( targets, values, payloads, NO_PREDECESSOR, + bytes32("1") + ); + } + + function testProposerCantExecute() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_ONE); + timelockController.execute( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, EMPTY_SALT ); + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_TWO); + timelockController.execute( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, + bytes32("1") + ); + } + + function testProposerCanCancel() public { + vm.expectRevert("TimelockController: operation cannot be cancelled"); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } + timelockController.cancel(EMPTY_SALT); + + vm.expectRevert("TimelockController: operation cannot be cancelled"); + vm.prank(PROPOSER_TWO); + timelockController.cancel(EMPTY_SALT); + } + + // Executor + + function testExecutorCantBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_ONE); timelockController.schedule_batch( targets, values, @@ -2143,93 +2276,174 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_TWO); + timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT + bytes32("1"), + MIN_DELAY ); + } - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID + function testExecutorCantSchedule() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_ONE); + timelockController.schedule( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_TWO); + timelockController.schedule( + address(0), + 0, + bytes(""), + NO_PREDECESSOR, + bytes32("1"), + MIN_DELAY ); - assertEq(operationTimestamp, DONE_TIMESTAMP); } - function testProposeValueProposal() public { - address target = address(counter); - uint256 value = 1 wei; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector + function testExecutorCanBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT ); - // Transfer to TimelockController - payable(address(timelockController)).transfer(value); + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_TWO); + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + bytes32("1") + ); + } - bytes32 operationID = timelockController.hash_operation( - target, - value, - payload, + function testExecutorCanExecute() public { + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.execute( + address(0), + 0, + bytes(""), NO_PREDECESSOR, EMPTY_SALT ); - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_TWO); + timelockController.execute( + address(0), 0, - target, - value, - payload, + bytes(""), + NO_PREDECESSOR, + bytes32("1") + ); + } + + function testExecutorCantCancel() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_ONE); + timelockController.cancel(EMPTY_SALT); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_TWO); + timelockController.cancel(EMPTY_SALT); + } + + // Stanger + + function testStrangerCantBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.schedule_batch( + targets, + values, + payloads, NO_PREDECESSOR, + EMPTY_SALT, MIN_DELAY ); + } + + function testStrangerCantSchedule() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); timelockController.schedule( - target, - value, - payload, + address(0), + 0, + bytes(""), NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); + } - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - value, - payload + function testStrangerCantBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory values = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT ); + } + + function testStrangerCantExecute() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); timelockController.execute( - target, - value, - payload, + address(0), + 0, + bytes(""), NO_PREDECESSOR, EMPTY_SALT ); + } - uint256 operationTimestamp = timelockController.get_timestamp( - operationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(address(counter).balance, value); + function testStrangerCantCancel() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.cancel(EMPTY_SALT); + } + + function testCancellerCanCancelOperation() public { + bytes32 operationID = _cancelOperation(); + + vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.Cancelled(operationID); + timelockController.cancel(operationID); + assertFalse(timelockController.is_operation(operationID)); } } From 17c1b551ff6087e413a809f4adfb75af396be138 Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Wed, 24 Jan 2024 02:36:40 +0100 Subject: [PATCH 35/46] Update TimelockController.t.sol --- test/governance/TimelockController.t.sol | 2436 ++++++++++++++++------ 1 file changed, 1785 insertions(+), 651 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 88430c83..73f624a8 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -4,6 +4,13 @@ pragma solidity ^0.8.23; import {Test} from "forge-std/Test.sol"; import {VyperDeployer} from "utils/VyperDeployer.sol"; +import {ERC721} from "openzeppelin/token/ERC721/ERC721.sol"; +import {ERC1155} from "openzeppelin/token/ERC1155/ERC1155.sol"; + +import {IERC165} from "openzeppelin/utils/introspection/IERC165.sol"; +import {IAccessControl} from "openzeppelin/access/IAccessControl.sol"; +import {IERC1155Receiver} from "openzeppelin/token/ERC1155/IERC1155Receiver.sol"; + import {ITimelockController} from "./interfaces/ITimelockController.sol"; contract TimelockControllerTest is Test { @@ -179,57 +186,6 @@ contract TimelockControllerTest is Test { } } - function _scheduleSingleBatchedOperation() - internal - returns ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) - { - targets = new address[](1); - targets[0] = address(counter); - - values = new uint256[](1); - values[0] = 0; - - payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - // Schedule batch execution - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - } - function _laterDelay(uint256 newMinDelay) internal { vm.startPrank(address(timelockController)); vm.expectEmit(); @@ -241,58 +197,6 @@ contract TimelockControllerTest is Test { vm.stopPrank(); } - function _executeOperation( - uint256 num - ) - internal - returns ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) - { - targets = new address[](1); - targets[0] = address(counter); - - values = new uint256[](1); - values[0] = 0; - - payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, num); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY + 2 days); - } - function _cancelOperation() internal returns (bytes32 operationID) { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -342,97 +246,138 @@ contract TimelockControllerTest is Test { } /*////////////////////////////////////////////////////////////// - OPERATION TESTS + OPERATION TESTS //////////////////////////////////////////////////////////////*/ - function testRevertWhenLessThanMinDelay() public { - address target = address(timelockController); - uint256 value = 0; - bytes memory data = abi.encodeWithSelector( - timelockController.update_delay.selector, - 0 + function testOperationComplete() public { + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); + + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT ); - vm.expectRevert("TimelockController: insufficient delay"); + assertEq(counter.number(), 0); + vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); timelockController.schedule( target, - value, - data, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, - MIN_DELAY - 1 + MIN_DELAY ); - } - function testUpdatesDelayAtLeastMinDelay() public { - vm.prank(address(timelockController)); - timelockController.update_delay(0); // set min delay to 0 + vm.warp(block.timestamp + MIN_DELAY); - address target = address(timelockController); - uint256 value = 0; - bytes memory data = abi.encodeWithSelector( - timelockController.update_delay.selector, - MIN_DELAY + vm.prank(EXECUTOR_ONE); + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT ); - bytes32 id = timelockController.hash_operation( + assertEq(counter.number(), 1); + } + + function testOperationAlreadyScheduled() public { + address target = address(0); + uint256 amount = 0; + bytes memory payload = bytes(""); + + bytes32 operationID = timelockController.hash_operation( target, - value, - data, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); - vm.prank(PROPOSER_ONE); + vm.startPrank(PROPOSER_ONE); vm.expectEmit(); emit ITimelockController.CallScheduled( - id, + operationID, 0, target, - value, - data, + amount, + payload, NO_PREDECESSOR, - 1 + MIN_DELAY ); timelockController.schedule( target, - value, - data, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, - 1 + MIN_DELAY ); - vm.warp(block.timestamp + 1); - - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted(id, 0, target, value, data); - timelockController.execute( + vm.expectRevert("TimelockController: operation already scheduled"); + timelockController.schedule( target, - value, - data, + amount, + payload, NO_PREDECESSOR, - EMPTY_SALT + EMPTY_SALT, + MIN_DELAY ); - - uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, MIN_DELAY); } - function testUpdatesMinDelay() public { - address target = address(timelockController); - uint256 value = 0; - bytes memory data = abi.encodeWithSelector( - timelockController.update_delay.selector, - MIN_DELAY + function testOperationInsufficientDelay() public { + address target = address(0); + uint256 amount = 0; + bytes memory payload = bytes(""); + + vm.expectRevert("TimelockController: insufficient delay"); + vm.prank(PROPOSER_ONE); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY - 1 ); + } + + function testOperationEqualAndGreaterMinDelay() public { + address target = address(0); + uint256 amount = 0; + bytes memory payload = bytes(""); - bytes32 id = timelockController.hash_operation( + bytes32 operationID = timelockController.hash_operation( target, - value, - data, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); @@ -440,136 +385,1384 @@ contract TimelockControllerTest is Test { vm.prank(PROPOSER_ONE); vm.expectEmit(); emit ITimelockController.CallScheduled( - id, + operationID, 0, target, - value, - data, + amount, + payload, NO_PREDECESSOR, MIN_DELAY ); timelockController.schedule( target, - value, - data, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); - vm.warp(block.timestamp + MIN_DELAY); + assertEq(timelockController.is_operation(operationID), true); - vm.prank(EXECUTOR_ONE); + operationID = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + bytes32("1") + ); + + vm.prank(PROPOSER_ONE); vm.expectEmit(); - emit ITimelockController.CallExecuted(id, 0, target, value, data); - timelockController.execute( + emit ITimelockController.CallScheduled( + operationID, + 0, target, - value, - data, + amount, + payload, NO_PREDECESSOR, - EMPTY_SALT + MIN_DELAY + 1 + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + bytes32("1"), + MIN_DELAY + 1 ); - uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, 2 days); + assertEq(timelockController.is_operation(operationID), true); } - /*////////////////////////////////////////////////////////////// - BATCHED OPERATION TESTS - //////////////////////////////////////////////////////////////*/ + function testOperationMinDelayUpdate() public { + address target = address(0); + uint256 amount = 0; + bytes memory payload = bytes(""); - function testHashesBatchedOperationsCorrectly() public { - address[] memory targets = new address[](2); - targets[0] = address(this); - targets[1] = address(this); + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - uint256[] memory values = new uint256[](2); - values[0] = 0; - values[1] = 1; + vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); - bytes[] memory payloads = new bytes[](2); - payloads[0] = abi.encodeWithSelector( - this.testHashesBatchedOperationsCorrectly.selector + uint256 operationTimestampBefore = timelockController.get_timestamp( + operationID ); - payloads[1] = abi.encodeWithSelector( - this.testHashesBatchedOperationsCorrectly.selector + + // Set a new delay value + vm.prank(address(timelockController)); + timelockController.update_delay(MIN_DELAY + 31 days); + + // New delay value should only apply on future operations, not existing ones + uint256 operationTimestampAfter = timelockController.get_timestamp( + operationID ); + assertEq(operationTimestampAfter, operationTimestampBefore); + } - bytes32 predecessor = NO_PREDECESSOR; - bytes32 salt = EMPTY_SALT; + function testOperationOperationIsNotReady() public { + address[] memory targets = new address[](1); + targets[0] = address(0); - bytes32 hashedOperation = timelockController.hash_operation_batch( + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = bytes(""); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, - predecessor, - salt - ); - bytes32 expectedHash = keccak256( - abi.encode(targets, values, payloads, predecessor, salt) + NO_PREDECESSOR, + EMPTY_SALT ); - assertEq(hashedOperation, expectedHash); - } - // function testProposerCanBatchSchedule() public { - // address[] memory targets = new address[](calls.length); - // uint256[] memory values = new uint256[](calls.length); - // bytes[] memory payloads = new bytes[](calls.length); - - // for (uint256 i = 0; i < calls.length; ++i) { - // targets[i] = calls[i].target; - // values[i] = calls[i].value; - // payloads[i] = calls[i].data; - // } - - // bytes32 batchedOperationID = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // assertEq(timelockController.is_operation(batchedOperationID), false); - - // vm.startPrank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // batchedOperationID, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // assertEq(timelockController.is_operation(batchedOperationID), true); - // } - - function testRevertWhenLaterDelayTooLow() public { - uint256 newMinDelay = 31 days; - _laterDelay(newMinDelay); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY - 2 days); + + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + } + + function testOperationPredecessorNotExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + bytes32 batchedOperationID2 = timelockController.hash_operation_batch( + targets, + values, + payloads, + batchedOperationID, + EMPTY_SALT + ); + + // Schedule dependent job + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID2, + i, + targets[i], + values[i], + payloads[i], + batchedOperationID, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + batchedOperationID, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + batchedOperationID, + EMPTY_SALT + ); + } + + function testOperationPredecessorNotScheduled() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + vm.startPrank(PROPOSER_ONE); + + // Prepare predecessor job + bytes32 operationOneID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + bytes32 operationOneID2 = timelockController.hash_operation_batch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT + ); + + // Schedule dependent job + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationOneID2, + i, + targets[i], + values[i], + payloads[i], + operationOneID, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + operationOneID, + EMPTY_SALT + ); + } + + function testOperationPredecessorInvalid() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // Prepare invalid predecessor + bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + invalidPredecessor, + EMPTY_SALT + ); + + // Schedule dependent job + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + invalidPredecessor, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + invalidPredecessor, + EMPTY_SALT, + MIN_DELAY + ); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + invalidPredecessor, + EMPTY_SALT + ); + } + + function testOperationTargetRevert() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + // Schedule a job where one target will revert + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("Transaction reverted"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + } + + function testOperationPredecessorMultipleNotExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + // Schedule predecessor job + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); + + // Schedule dependent job + vm.prank(PROPOSER_ONE); + timelockController.schedule_batch( + targets, + values, + payloads, + batchedOperationID, + EMPTY_SALT, + MIN_DELAY + ); + + // Check that executing the dependent job reverts + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + values, + payloads, + batchedOperationID, + EMPTY_SALT + ); + } + + function testOperationCancelFinished() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY + 1); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.prank(PROPOSER_ONE); + vm.expectRevert("TimelockController: operation cannot be cancelled"); + timelockController.cancel(batchedOperationID); + } + + function testOperationPendingIfNotYetExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + bool is_operation_pending = timelockController.is_operation_pending( + batchedOperationID + ); + assertEq(is_operation_pending, true); + } + + function testOperationPendingIfExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + bool is_operation_pending = timelockController.is_operation_pending( + batchedOperationID + ); + assertEq(is_operation_pending, false); + } + + function testOperationReadyOnTheExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + + bool is_operation_ready = timelockController.is_operation_ready( + batchedOperationID + ); + assertEq(is_operation_ready, true); + } + + function testOperationReadyAfterTheExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY + 1 days); + + bool is_operation_ready = timelockController.is_operation_ready( + batchedOperationID + ); + assertEq(is_operation_ready, true); + } + + function testOperationReadyBeforeTheExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY - 1 days); + + bool is_operation_ready = timelockController.is_operation_ready( + batchedOperationID + ); + assertEq(is_operation_ready, false); + } + + function testOperationHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + bool is_operation_ready = timelockController.is_operation_ready( + batchedOperationID + ); + assertEq(is_operation_ready, false); + + bool is_operation_done = timelockController.is_operation_done( + batchedOperationID + ); + assertEq(is_operation_done, true); + } + + function testOperationHasNotBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + bool is_operation_done = timelockController.is_operation_done( + batchedOperationID + ); + assertEq(is_operation_done, false); + } + + function testOperationTimestampHasNotBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationID + ); + assertEq(operationTimestamp, block.timestamp + MIN_DELAY); + } + + function testOperationTimestampHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationID + ); + assertEq(operationTimestamp, DONE_TIMESTAMP); + } + + function testOperationValue() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 1 wei; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // Transfer to TimelockController + payable(address(timelockController)).transfer(values[0]); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationID + ); + assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(address(counter).balance, values[0]); + } + + function testOperationERC1155() public { + ERC1155Mock erc1155 = new ERC1155Mock(""); + erc1155.mint(address(timelockController), 1, 1, bytes("")); + + assertEq(erc1155.balanceOf(address(timelockController), 1), 1); + + address[] memory targets = new address[](1); + targets[0] = address(erc1155); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + ERC1155Mock.burn.selector, + address(timelockController), + 1, + 1 + ); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationID + ); + assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(erc1155.balanceOf(address(timelockController), 1), 0); + } + + function testOperationERC721() public { + ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); + erc721.mint(address(timelockController), 1); + + assertEq(erc721.balanceOf(address(timelockController)), 1); + + address[] memory targets = new address[](1); + targets[0] = address(erc721); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationID + ); + assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(erc721.balanceOf(address(timelockController)), 0); + } + + /*////////////////////////////////////////////////////////////// + BATCH TESTS + //////////////////////////////////////////////////////////////*/ + + function testBatchComplete() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + assertEq(counter.number(), 0); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + assertEq(counter.number(), 1); + } + + function testBatchOperationAlreadyScheduled() public { + address[] memory targets = new address[](1); + targets[0] = address(0); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = bytes(""); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.expectRevert("TimelockController: operation already scheduled"); + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + } + + function testBatchInsufficientDelay() public { + address[] memory targets = new address[](1); + targets[0] = address(0); - address[] memory targets = new address[](calls.length); - uint256[] memory values = new uint256[](calls.length); - bytes[] memory payloads = new bytes[](calls.length); + uint256[] memory values = new uint256[](1); + values[0] = 0; - for (uint256 i = 0; i < calls.length; ++i) { - targets[i] = calls[i].target; - values[i] = calls[i].value; - payloads[i] = calls[i].data; - } + bytes[] memory payloads = new bytes[](1); + payloads[0] = bytes(""); vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); @@ -579,77 +1772,19 @@ contract TimelockControllerTest is Test { payloads, NO_PREDECESSOR, EMPTY_SALT, - newMinDelay - 1 - ); - } - - // function testProposerCanBatchScheduleGreaterEqualToLaterMinDelay() public { - // uint256 newMinDelay = 31 days; - // _laterDelay(newMinDelay); - - // address[] memory targets = new address[](calls.length); - // uint256[] memory values = new uint256[](calls.length); - // bytes[] memory payloads = new bytes[](calls.length); - - // for (uint256 i = 0; i < calls.length; ++i) { - // targets[i] = calls[i].target; - // values[i] = calls[i].value; - // payloads[i] = calls[i].data; - // } - - // bytes32 batchedOperationID = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // assertEq(timelockController.is_operation(batchedOperationID), false); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // batchedOperationID, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // newMinDelay - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // newMinDelay - // ); - - // assertEq(timelockController.is_operation(batchedOperationID), true); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID - // ); - // assertEq(operationTimestamp, block.timestamp + newMinDelay); - // } - - function testUpdateDelayDoesNotChangeExistingOperationTimestamps() public { - uint256 newMinDelay = 31 days; - _laterDelay(newMinDelay); + MIN_DELAY - 1 + ); + } - address[] memory targets = new address[](calls.length); - uint256[] memory values = new uint256[](calls.length); - bytes[] memory payloads = new bytes[](calls.length); + function testBatchEqualAndGreaterMinDelay() public { + address[] memory targets = new address[](1); + targets[0] = address(0); - for (uint256 i = 0; i < calls.length; ++i) { - targets[i] = calls[i].target; - values[i] = calls[i].value; - payloads[i] = calls[i].data; - } + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = bytes(""); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -669,7 +1804,7 @@ contract TimelockControllerTest is Test { values[i], payloads[i], NO_PREDECESSOR, - newMinDelay + MIN_DELAY ); } timelockController.schedule_batch( @@ -678,61 +1813,53 @@ contract TimelockControllerTest is Test { payloads, NO_PREDECESSOR, EMPTY_SALT, - newMinDelay - ); - - uint256 operationTimestampBefore = timelockController.get_timestamp( - batchedOperationID - ); - - // Set a new delay value - vm.prank(address(timelockController)); - timelockController.update_delay(newMinDelay + 1); - - // New delay value should only apply on future operations, not existing ones - uint256 operationTimestampAfter = timelockController.get_timestamp( - batchedOperationID + MIN_DELAY ); - assertEq(operationTimestampAfter, operationTimestampBefore); - } - function testRevertWhenNotProposer() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); + assertEq(timelockController.is_operation(batchedOperationID), true); - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.schedule_batch( + batchedOperationID = timelockController.hash_operation_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + bytes32("1") ); - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + 1 + ); + } timelockController.schedule_batch( targets, values, payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + bytes32("1"), + MIN_DELAY + 1 ); + + assertEq(timelockController.is_operation(batchedOperationID), true); } - function testRevertWhenScheduleIfOperationScheduled() public { + function testBatchMinDelayUpdate() public { address[] memory targets = new address[](1); - targets[0] = address(counter); + targets[0] = address(0); uint256[] memory values = new uint256[](1); values[0] = 0; bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + payloads[0] = bytes(""); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -742,7 +1869,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - vm.startPrank(PROPOSER_ONE); + vm.prank(PROPOSER_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(); emit ITimelockController.CallScheduled( @@ -764,49 +1891,30 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - vm.expectRevert("TimelockController: operation already scheduled"); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + uint256 operationTimestampBefore = timelockController.get_timestamp( + batchedOperationID + ); + + // Set a new delay value + vm.prank(address(timelockController)); + timelockController.update_delay(MIN_DELAY + 31 days); + + // New delay value should only apply on future operations, not existing ones + uint256 operationTimestampAfter = timelockController.get_timestamp( + batchedOperationID ); + assertEq(operationTimestampAfter, operationTimestampBefore); } - function testRevertWhenScheduleIfDelayLessThanMinDelay() public { + function testBatchOperationIsNotReady() public { address[] memory targets = new address[](1); - targets[0] = address(counter); + targets[0] = address(0); uint256[] memory values = new uint256[](1); values[0] = 0; bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - vm.expectRevert("TimelockController: insufficient delay"); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - 1 - ); - } - - function testRevertWhenMultipleOperationNotReady() public { - address[] memory targets = new address[](calls.length); - uint256[] memory values = new uint256[](calls.length); - bytes[] memory payloads = new bytes[](calls.length); - - for (uint256 i = 0; i < calls.length; ++i) { - targets[i] = calls[i].target; - values[i] = calls[i].value; - payloads[i] = calls[i].data; - } + payloads[0] = bytes(""); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -851,7 +1959,7 @@ contract TimelockControllerTest is Test { ); } - function testRevertWhenPredecessorOperationNotExecuted() public { + function testBatchPredecessorNotExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -935,7 +2043,7 @@ contract TimelockControllerTest is Test { ); } - function testRevertWhenPredecessorOperationNotScheduled() public { + function testBatchPredecessorNotScheduled() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1000,7 +2108,7 @@ contract TimelockControllerTest is Test { ); } - function testRevertWhenPredecessorOperationInvalid() public { + function testBatchPredecessorInvalid() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1057,7 +2165,7 @@ contract TimelockControllerTest is Test { ); } - function testRevertWhenOneTargetReverts() public { + function testBatchTargetRevert() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1110,106 +2218,7 @@ contract TimelockControllerTest is Test { ); } - function testExecutorCanBatchExecuteOperation() public { - ( - address[] memory targets, - uint256[] memory values, - bytes[] memory payloads - ) = _scheduleSingleBatchedOperation(); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bytes32 operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - uint256 operationTimestamp = timelockController.get_timestamp( - operationID - ); - - assertEq(operationTimestamp, DONE_TIMESTAMP); - } - - function testRevertWhenSingleOperationNotReady() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - vm.warp(block.timestamp + MIN_DELAY - 2 days); - vm.expectRevert("TimelockController: operation is not ready"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testRevertWhenPredecessorMultipleOperationNotExecuted() public { + function testBatchPredecessorMultipleNotExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1250,86 +2259,33 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); - - // Schedule dependent job - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( - targets, - values, - payloads, - batchedOperationID, - EMPTY_SALT, - MIN_DELAY - ); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - batchedOperationID, - EMPTY_SALT - ); - } - - function testRevertWhenTargetReverts() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - // Schedule predecessor job - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - + payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); + + // Schedule dependent job + vm.prank(PROPOSER_ONE); + timelockController.schedule_batch( + targets, + values, + payloads, + batchedOperationID, + EMPTY_SALT, + MIN_DELAY + ); + + // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("Transaction reverted"); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); timelockController.execute_batch( targets, values, payloads, - NO_PREDECESSOR, + batchedOperationID, EMPTY_SALT ); } - function testRevertWhenFinishedOperation() public { + function testBatchCancelFinished() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1393,7 +2349,7 @@ contract TimelockControllerTest is Test { timelockController.cancel(batchedOperationID); } - function testTrueIfScheduledOperatonNotYetExecuted() public { + function testBatchPendingIfNotYetExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1439,7 +2395,7 @@ contract TimelockControllerTest is Test { assertEq(is_operation_pending, true); } - function testFalseIfPendingOperationHasBeenExecuted() public { + function testBatchPendingIfExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1505,7 +2461,7 @@ contract TimelockControllerTest is Test { assertEq(is_operation_pending, false); } - function testTrueIfOnTheDelayedExecutionTime() public { + function testBatchReadyOnTheExecutionTime() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1553,7 +2509,7 @@ contract TimelockControllerTest is Test { assertEq(is_operation_ready, true); } - function testTrueIfAfterTheDelayedExecutionTime() public { + function testBatchReadyAfterTheExecutionTime() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1601,7 +2557,7 @@ contract TimelockControllerTest is Test { assertEq(is_operation_ready, true); } - function testFalseIfBeforeTheDelayedExecutionTime() public { + function testBatchReadyBeforeTheExecutionTime() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1649,7 +2605,7 @@ contract TimelockControllerTest is Test { assertEq(is_operation_ready, false); } - function testFalseIfReadyOperationHasBeenExecuted() public { + function testBatchHasBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1713,9 +2669,14 @@ contract TimelockControllerTest is Test { batchedOperationID ); assertEq(is_operation_ready, false); + + bool is_operation_done = timelockController.is_operation_done( + batchedOperationID + ); + assertEq(is_operation_done, true); } - function testFalseItTheOperationHasNotBeenExecuted() public { + function testBatchHasNotBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1761,7 +2722,53 @@ contract TimelockControllerTest is Test { assertEq(is_operation_done, false); } - function testTrueIfOperationHasBeenExecuted() public { + function testBatchTimestampHasNotBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = address(counter); + + uint256[] memory values = new uint256[](1); + values[0] = 0; + + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + bytes32 batchedOperationID = timelockController.hash_operation_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationID + ); + assertEq(operationTimestamp, block.timestamp + MIN_DELAY); + } + + function testBatchTimestampHasBeenExecuted() public { address[] memory targets = new address[](1); targets[0] = address(counter); @@ -1821,24 +2828,25 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - bool is_operation_done = timelockController.is_operation_done( + uint256 operationTimestamp = timelockController.get_timestamp( batchedOperationID ); - assertEq(is_operation_done, true); + assertEq(operationTimestamp, DONE_TIMESTAMP); } - function testReturnsTheCorrectTimestampIfTheOperationHasNotBeenExecuted() - public - { + function testBatchValue() public { address[] memory targets = new address[](1); targets[0] = address(counter); uint256[] memory values = new uint256[](1); - values[0] = 0; + values[0] = 1 wei; bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + // Transfer to TimelockController + payable(address(timelockController)).transfer(values[0]); + bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, values, @@ -1869,21 +2877,53 @@ contract TimelockControllerTest is Test { MIN_DELAY ); + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + uint256 operationTimestamp = timelockController.get_timestamp( batchedOperationID ); - assertEq(operationTimestamp, block.timestamp + MIN_DELAY); + assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(address(counter).balance, values[0]); } - function testReturnsOneIfOperationHasBeenExecuted() public { + function testBatchERC1155() public { + ERC1155Mock erc1155 = new ERC1155Mock(""); + erc1155.mint(address(timelockController), 1, 1, bytes("")); + + assertEq(erc1155.balanceOf(address(timelockController), 1), 1); + address[] memory targets = new address[](1); - targets[0] = address(counter); + targets[0] = address(erc1155); uint256[] memory values = new uint256[](1); values[0] = 0; bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + payloads[0] = abi.encodeWithSelector( + ERC1155Mock.burn.selector, + address(timelockController), + 1, + 1 + ); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -1916,6 +2956,7 @@ contract TimelockControllerTest is Test { ); vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(); @@ -1939,39 +2980,23 @@ contract TimelockControllerTest is Test { batchedOperationID ); assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(erc1155.balanceOf(address(timelockController), 1), 0); } - /*////////////////////////////////////////////////////////////// - SANITY CHECKS TESTS - //////////////////////////////////////////////////////////////*/ - - function testReturnsLaterMinDelayForCalls() public { - uint256 newMinDelay = 31 days; - _laterDelay(newMinDelay); - uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, newMinDelay); - } - - function testCanReceiveETH() public { - vm.prank(ADMIN); - payable(address(timelockController)).transfer(0.5 ether); - assertEq(address(timelockController).balance, 0.5 ether); - } + function testBatchERC721() public { + ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); + erc721.mint(address(timelockController), 1); - function testFalseIfNotAnOperation() public { - bool is_operation = timelockController.is_operation(bytes32("non-op")); - assertEq(is_operation, false); - } + assertEq(erc721.balanceOf(address(timelockController)), 1); - function testTrueIfAnOperation() public { address[] memory targets = new address[](1); - targets[0] = address(counter); + targets[0] = address(erc721); uint256[] memory values = new uint256[](1); values[0] = 0; bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -2003,74 +3028,149 @@ contract TimelockControllerTest is Test { MIN_DELAY ); - bool is_operation = timelockController.is_operation(batchedOperationID); - assertEq(is_operation, true); + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallExecuted( + batchedOperationID, + i, + targets[i], + values[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + values, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationID + ); + assertEq(operationTimestamp, DONE_TIMESTAMP); + assertEq(erc721.balanceOf(address(timelockController)), 0); } - function testProposeValueProposal() public { - address target = address(counter); - uint256 value = 1 wei; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector + /*////////////////////////////////////////////////////////////// + SANITY CHECKS TESTS + //////////////////////////////////////////////////////////////*/ + + function testReturnsLaterMinDelayForCalls() public { + uint256 newMinDelay = 31 days; + _laterDelay(newMinDelay); + uint256 minDelay = timelockController.get_minimum_delay(); + assertEq(minDelay, newMinDelay); + } + + function testCanReceiveEther() public { + vm.prank(ADMIN); + payable(address(timelockController)).transfer(0.5 ether); + assertEq(address(timelockController).balance, 0.5 ether); + } + + function testInvalidOperation() public { + bool is_operation = timelockController.is_operation(bytes32("non-op")); + assertEq(is_operation, false); + } + + // ERC165 `supportsInterface` + + function testSupportsInterfaceSuccess() public { + assertTrue( + timelockController.supportsInterface(type(IERC165).interfaceId) + ); + assertTrue( + timelockController.supportsInterface( + type(IAccessControl).interfaceId + ) + ); + assertTrue( + timelockController.supportsInterface( + type(IERC1155Receiver).interfaceId + ) ); + } - // Transfer to TimelockController - payable(address(timelockController)).transfer(value); + function testSupportsInterfaceSuccessGasCost() public { + uint256 startGas = gasleft(); + timelockController.supportsInterface(type(IERC165).interfaceId); + uint256 gasUsed = startGas - gasleft(); + assertTrue( + gasUsed <= 30_000 && + timelockController.supportsInterface(type(IERC165).interfaceId) + ); + } - bytes32 operationID = timelockController.hash_operation( - target, - value, - payload, - NO_PREDECESSOR, - EMPTY_SALT + function testSupportsInterfaceInvalidInterfaceId() public { + assertTrue(!timelockController.supportsInterface(0x0011bbff)); + } + + function testSupportsInterfaceInvalidInterfaceIdGasCost() public { + uint256 startGas = gasleft(); + timelockController.supportsInterface(0x0011bbff); + uint256 gasUsed = startGas - gasleft(); + assertTrue( + gasUsed <= 30_000 && + !timelockController.supportsInterface(0x0011bbff) ); + } - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - value, - payload, - NO_PREDECESSOR, - MIN_DELAY + // Hash calculation + function testHashOperationBatch() public { + address[] memory targets = new address[](2); + targets[0] = address(this); + targets[1] = address(this); + + uint256[] memory values = new uint256[](2); + values[0] = 0; + values[1] = 1; + + bytes[] memory payloads = new bytes[](2); + payloads[0] = abi.encodeWithSelector( + this.testHashOperationBatch.selector ); - timelockController.schedule( - target, - value, - payload, + payloads[1] = abi.encodeWithSelector( + this.testHashOperationBatch.selector + ); + + bytes32 hashedOperation = timelockController.hash_operation_batch( + targets, + values, + payloads, NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + EMPTY_SALT + ); + bytes32 expectedHash = keccak256( + abi.encode(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT) ); + assertEq(hashedOperation, expectedHash); + } - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - value, - payload + function testHashOperation() public { + address target = address(this); + uint256 amount = 1; + bytes memory payload = abi.encodeWithSelector( + this.testHashOperationBatch.selector ); - timelockController.execute( + + bytes32 hashedOperation = timelockController.hash_operation( target, - value, + amount, payload, NO_PREDECESSOR, EMPTY_SALT ); - - uint256 operationTimestamp = timelockController.get_timestamp( - operationID + bytes32 expectedHash = keccak256( + abi.encode(target, amount, payload, NO_PREDECESSOR, EMPTY_SALT) ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(address(counter).balance, value); + assertEq(hashedOperation, expectedHash); } - // TODO Add supportsInterface checks for // TODO: Add NFTs tests /*////////////////////////////////////////////////////////////// @@ -2078,6 +3178,7 @@ contract TimelockControllerTest is Test { //////////////////////////////////////////////////////////////*/ // Timelock + function testRevertWhenNotTimelock() public { vm.expectRevert("TimelockController: caller must be timelock"); vm.prank(STRANGER); @@ -2436,6 +3537,7 @@ contract TimelockControllerTest is Test { timelockController.cancel(EMPTY_SALT); } + // TODO: Move this somewhere in correct place function testCancellerCanCancelOperation() public { bytes32 operationID = _cancelOperation(); @@ -2447,6 +3549,38 @@ contract TimelockControllerTest is Test { } } +contract ERC1155Mock is ERC1155 { + constructor(string memory uri) ERC1155(uri) {} + + function mint( + address to, + uint256 id, + uint256 value, + bytes memory data + ) external { + _mint(to, id, value, data); + } + + function burn(address from, uint256 id, uint256 value) external { + _burn(from, id, value); + } +} + +contract ERC721Mock is ERC721 { + constructor( + string memory name, + string memory symbol + ) ERC721(name, symbol) {} + + function mint(address to, uint256 tokenId) external { + _mint(to, tokenId); + } + + function burn(uint256 tokenId) external { + _burn(tokenId); + } +} + contract Counter { address private timelock; uint256 public number; From fcb92091ba3fff49d6b92ec88afc910dab52e6ac Mon Sep 17 00:00:00 2001 From: cairo <101215230+cairoeth@users.noreply.github.com> Date: Wed, 24 Jan 2024 02:57:01 +0100 Subject: [PATCH 36/46] =?UTF-8?q?=E2=9C=85=20Single=20operation=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/governance/TimelockController.t.sol | 1194 ++++++++++------------ 1 file changed, 534 insertions(+), 660 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 73f624a8..d924281f 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -16,8 +16,6 @@ import {ITimelockController} from "./interfaces/ITimelockController.sol"; contract TimelockControllerTest is Test { uint256 internal constant MIN_DELAY = 2 days; uint256 internal constant DONE_TIMESTAMP = 1; - uint256 internal constant DELAY_ONE_MONTH = 31 days; - uint256 internal constant DELAY_TWO_DAYS = 48 hours; address private immutable ADMIN = address(this); address private constant PROPOSER_ONE = address(0x1); @@ -32,22 +30,12 @@ contract TimelockControllerTest is Test { address[2] private PROPOSERS; address[2] private EXECUTORS; - Call[] internal calls; - Counter private counter; - struct Call { - address target; - uint256 value; - bytes data; - } - VyperDeployer private vyperDeployer = new VyperDeployer(); ITimelockController private timelockController; - address private deployer = address(vyperDeployer); - /*////////////////////////////////////////////////////////////// SET UP //////////////////////////////////////////////////////////////*/ @@ -79,21 +67,6 @@ contract TimelockControllerTest is Test { ); counter = new Counter(address(timelockController)); - - calls.push( - Call({ - target: address(counter), - value: 0, - data: abi.encodeWithSelector(Counter.increment.selector) - }) - ); - calls.push( - Call({ - target: address(counter), - value: 0, - data: abi.encodeWithSelector(Counter.setNumber.selector, 10) - }) - ); } function testInitialSetup() public { @@ -484,40 +457,33 @@ contract TimelockControllerTest is Test { } function testOperationOperationIsNotReady() public { - address[] memory targets = new address[](1); - targets[0] = address(0); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = bytes(""); + address target = address(0); + uint256 amount = 0; + bytes memory payload = bytes(""); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY @@ -527,81 +493,74 @@ contract TimelockControllerTest is Test { vm.expectRevert("TimelockController: operation is not ready"); vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, + timelockController.execute( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); } function testOperationPredecessorNotExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.startPrank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); - bytes32 batchedOperationID2 = timelockController.hash_operation_batch( - targets, - values, - payloads, - batchedOperationID, + bytes32 operationID2 = timelockController.hash_operation( + target, + amount, + payload, + operationID, EMPTY_SALT ); // Schedule dependent job - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID2, - i, - targets[i], - values[i], - payloads[i], - batchedOperationID, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - batchedOperationID, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID2, + 0, + target, + amount, + payload, + operationID, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + operationID, EMPTY_SALT, MIN_DELAY ); @@ -609,64 +568,58 @@ contract TimelockControllerTest is Test { // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - batchedOperationID, + timelockController.execute( + target, + amount, + payload, + operationID, EMPTY_SALT ); } function testOperationPredecessorNotScheduled() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - vm.startPrank(PROPOSER_ONE); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - // Prepare predecessor job - bytes32 operationOneID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID1 = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); - bytes32 operationOneID2 = timelockController.hash_operation_batch( - targets, - values, - payloads, - operationOneID, + bytes32 operationID2 = timelockController.hash_operation( + target, + amount, + payload, + operationID1, EMPTY_SALT ); // Schedule dependent job - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationOneID2, - i, - targets[i], - values[i], - payloads[i], - operationOneID, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - operationOneID, + vm.prank(PROPOSER_ONE); + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID2, + 0, + target, + amount, + payload, + operationID1, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + operationID1, EMPTY_SALT, MIN_DELAY ); @@ -674,56 +627,52 @@ contract TimelockControllerTest is Test { // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - operationOneID, + timelockController.execute( + target, + amount, + payload, + operationID1, EMPTY_SALT ); } function testOperationPredecessorInvalid() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); // Prepare invalid predecessor bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, invalidPredecessor, EMPTY_SALT ); // Schedule dependent job vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - invalidPredecessor, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + invalidPredecessor, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, invalidPredecessor, EMPTY_SALT, MIN_DELAY @@ -731,348 +680,319 @@ contract TimelockControllerTest is Test { // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, + timelockController.execute( + target, + amount, + payload, invalidPredecessor, EMPTY_SALT ); } function testOperationTargetRevert() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.mockRevert.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); // Schedule a job where one target will revert vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("Transaction reverted"); vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, + timelockController.execute( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); } function testOperationPredecessorMultipleNotExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); // Schedule predecessor job vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); - payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); + payload = abi.encodeWithSelector(Counter.setNumber.selector, 1); // Schedule dependent job vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( - targets, - values, - payloads, - batchedOperationID, + timelockController.schedule( + target, + amount, + payload, + operationID, EMPTY_SALT, MIN_DELAY ); // Check that executing the dependent job reverts vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - batchedOperationID, + timelockController.execute( + target, + amount, + payload, + operationID, EMPTY_SALT ); } function testOperationCancelFinished() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); vm.warp(block.timestamp + MIN_DELAY + 1); + vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); vm.expectRevert("TimelockController: operation cannot be cancelled"); - timelockController.cancel(batchedOperationID); + timelockController.cancel(operationID); } function testOperationPendingIfNotYetExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); bool is_operation_pending = timelockController.is_operation_pending( - batchedOperationID + operationID ); assertEq(is_operation_pending, true); } function testOperationPendingIfExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); bool is_operation_pending = timelockController.is_operation_pending( - batchedOperationID + operationID ); assertEq(is_operation_pending, false); } function testOperationReadyOnTheExecutionTime() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY @@ -1081,46 +1001,41 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID + operationID ); assertEq(is_operation_ready, true); } function testOperationReadyAfterTheExecutionTime() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY @@ -1129,46 +1044,41 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY + 1 days); bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID + operationID ); assertEq(is_operation_ready, true); } function testOperationReadyBeforeTheExecutionTime() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY @@ -1177,46 +1087,41 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY - 1 days); bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID + operationID ); assertEq(is_operation_ready, false); } function testOperationHasBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY @@ -1224,162 +1129,145 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID + operationID ); assertEq(is_operation_ready, false); bool is_operation_done = timelockController.is_operation_done( - batchedOperationID + operationID ); assertEq(is_operation_done, true); } function testOperationHasNotBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); bool is_operation_done = timelockController.is_operation_done( - batchedOperationID + operationID ); assertEq(is_operation_done, false); } function testOperationTimestampHasNotBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID + operationID ); assertEq(operationTimestamp, block.timestamp + MIN_DELAY); } function testOperationTimestampHasBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + address target = address(counter); + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY @@ -1387,68 +1275,59 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID + operationID ); assertEq(operationTimestamp, DONE_TIMESTAMP); } - function testOperationValue() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 1 wei; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // Transfer to TimelockController - payable(address(timelockController)).transfer(values[0]); + function testFuzzOperationValue(uint256 amount) public { + address target = address(counter); + bytes memory payload = abi.encodeWithSelector( + Counter.increment.selector + ); - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, + bytes32 operationID = timelockController.hash_operation( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); + deal(address(timelockController), amount); + vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallScheduled( + operationID, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY @@ -1457,29 +1336,27 @@ contract TimelockControllerTest is Test { vm.warp(block.timestamp + MIN_DELAY); vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, + vm.expectEmit(); + emit ITimelockController.CallExecuted( + operationID, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, NO_PREDECESSOR, EMPTY_SALT ); uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID + operationID ); assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(address(counter).balance, values[0]); + assertEq(address(counter).balance, amount); } function testOperationERC1155() public { @@ -2834,18 +2711,17 @@ contract TimelockControllerTest is Test { assertEq(operationTimestamp, DONE_TIMESTAMP); } - function testBatchValue() public { + function testFuzzBatchValue(uint256 amount) public { address[] memory targets = new address[](1); targets[0] = address(counter); uint256[] memory values = new uint256[](1); - values[0] = 1 wei; + values[0] = amount; bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // Transfer to TimelockController - payable(address(timelockController)).transfer(values[0]); + deal(address(timelockController), amount); bytes32 batchedOperationID = timelockController.hash_operation_batch( targets, @@ -3613,8 +3489,6 @@ contract TimelockControllerInvariants is Test { ITimelockController private timelockController; TimelockControllerHandler private timelockControllerHandler; - address private deployer = address(vyperDeployer); - function setUp() public { address[] memory proposers = new address[](1); proposers[0] = address(this); From 6cb0531228112e59b3d456863b930b1381f3f5f0 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Mon, 29 Jan 2024 12:13:11 +0100 Subject: [PATCH 37/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Remove=20`receive`?= =?UTF-8?q?=20Function=20From=20Interface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/governance/interfaces/ITimelockController.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/governance/interfaces/ITimelockController.sol b/test/governance/interfaces/ITimelockController.sol index f541949f..b2e85177 100644 --- a/test/governance/interfaces/ITimelockController.sol +++ b/test/governance/interfaces/ITimelockController.sol @@ -61,8 +61,6 @@ interface ITimelockController is pure returns (bytes4); - receive() external payable; - function get_timestamp(bytes32 id) external view returns (uint256); function get_minimum_delay() external view returns (uint256); From 92b1285d2efff9de85343522926a508a0921768b Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Tue, 30 Jan 2024 13:56:24 +0100 Subject: [PATCH 38/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/governance/TimelockController.t.sol | 7495 ++++++++++---------- test/governance/mocks/CallReceiverMock.sol | 103 + test/tokens/mocks/ERC721ReceiverMock.sol | 6 +- 3 files changed, 4047 insertions(+), 3557 deletions(-) create mode 100644 test/governance/mocks/CallReceiverMock.sol diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index d924281f..e558f58a 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -4,427 +4,670 @@ pragma solidity ^0.8.23; import {Test} from "forge-std/Test.sol"; import {VyperDeployer} from "utils/VyperDeployer.sol"; -import {ERC721} from "openzeppelin/token/ERC721/ERC721.sol"; -import {ERC1155} from "openzeppelin/token/ERC1155/ERC1155.sol"; - import {IERC165} from "openzeppelin/utils/introspection/IERC165.sol"; import {IAccessControl} from "openzeppelin/access/IAccessControl.sol"; import {IERC1155Receiver} from "openzeppelin/token/ERC1155/IERC1155Receiver.sol"; +import {ERC721ReceiverMock} from "../tokens/mocks/ERC721ReceiverMock.sol"; +import {ERC1155ReceiverMock} from "../tokens/mocks/ERC1155ReceiverMock.sol"; +import {CallReceiverMock} from "./mocks/CallReceiverMock.sol"; + import {ITimelockController} from "./interfaces/ITimelockController.sol"; contract TimelockControllerTest is Test { - uint256 internal constant MIN_DELAY = 2 days; - uint256 internal constant DONE_TIMESTAMP = 1; - - address private immutable ADMIN = address(this); - address private constant PROPOSER_ONE = address(0x1); - address private constant PROPOSER_TWO = address(0x2); - address private constant EXECUTOR_ONE = address(0x3); - address private constant EXECUTOR_TWO = address(0x4); - address private constant STRANGER = address(0x99); - - bytes32 internal constant NO_PREDECESSOR = bytes32(""); - bytes32 internal constant EMPTY_SALT = bytes32(""); - - address[2] private PROPOSERS; - address[2] private EXECUTORS; - - Counter private counter; + bytes32 private constant DEFAULT_ADMIN_ROLE = bytes32(0); + bytes32 private constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); + bytes32 private constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); + bytes32 private constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); + + bytes4 private constant IERC721_TOKENRECEIVER_SELECTOR = + ERC721ReceiverMock.onERC721Received.selector; + bytes4 private constant IERC1155_TOKENRECEIVER_SINGLE_SELECTOR = + ERC1155ReceiverMock.onERC1155Received.selector; + bytes4 private constant IERC1155_TOKENRECEIVER_BATCH_SELECTOR = + ERC1155ReceiverMock.onERC1155BatchReceived.selector; + + uint256 private constant MIN_DELAY = 2 days; + uint256 private constant DONE_TIMESTAMP = 1; + + address private constant PROPOSER_ONE = + address(uint160(uint256(keccak256(abi.encodePacked("PROPOSER_ONE"))))); + address private constant PROPOSER_TWO = + address(uint160(uint256(keccak256(abi.encodePacked("PROPOSER_TWO"))))); + address private constant EXECUTOR_ONE = + address(uint160(uint256(keccak256(abi.encodePacked("EXECUTOR_ONE"))))); + address private constant EXECUTOR_TWO = + address(uint160(uint256(keccak256(abi.encodePacked("EXECUTOR_TWO"))))); + address private constant STRANGER = + address(uint160(uint256(keccak256(abi.encodePacked("STRANGER"))))); + + bytes32 private constant NO_PREDECESSOR = bytes32(""); + bytes32 private constant EMPTY_SALT = bytes32(""); + bytes32 private constant SALT = keccak256("WAGMI"); VyperDeployer private vyperDeployer = new VyperDeployer(); + CallReceiverMock private callReceiverMock = new CallReceiverMock(); ITimelockController private timelockController; - - /*////////////////////////////////////////////////////////////// - SET UP - //////////////////////////////////////////////////////////////*/ + ITimelockController private timelockControllerInitialEventEmptyAdmin; + ITimelockController private timelockControllerInitialEventNonEmptyAdmin; + + address private deployer = address(vyperDeployer); + address private self = address(this); + address private target = address(callReceiverMock); + address private timelockControllerAddr; + address private timelockControllerInitialEventEmptyAdminAddr; + address private timelockControllerInitialEventNonEmptyAdminAddr; + + address[2] private proposers = [PROPOSER_ONE, PROPOSER_TWO]; + address[2] private executors = [EXECUTOR_ONE, EXECUTOR_TWO]; + + /** + * @dev An `internal` helper function to check whether a specific role `role` + * is not assigned to an array of addresses with the length 2. + * @param accessControl The contract that implements the `IAccessControl` interface. + * @param role The 32-byte role definition. + * @param addresses The 20-byte array with the length 2 of accounts to be checked. + */ + function checkRoleNotSetForAddresses( + IAccessControl accessControl, + bytes32 role, + address[2] storage addresses + ) internal { + for (uint256 i = 0; i < addresses.length; ++i) { + assertTrue(!accessControl.hasRole(role, addresses[i])); + } + } function setUp() public { - PROPOSERS[0] = PROPOSER_ONE; - PROPOSERS[1] = PROPOSER_TWO; - - EXECUTORS[0] = EXECUTOR_ONE; - EXECUTORS[1] = EXECUTOR_TWO; - - address[] memory proposers = new address[](2); - proposers[0] = PROPOSER_ONE; - proposers[1] = PROPOSER_TWO; - - address[] memory executors = new address[](2); - executors[0] = EXECUTOR_ONE; - executors[1] = EXECUTOR_TWO; - - bytes memory args = abi.encode(MIN_DELAY, proposers, executors, ADMIN); + address[] memory proposers_ = new address[](2); + proposers_[0] = proposers[0]; + proposers_[1] = proposers[1]; + address[] memory executors_ = new address[](2); + executors_[0] = executors[0]; + executors_[1] = executors[1]; + + bytes memory args = abi.encode(MIN_DELAY, proposers_, executors_, self); timelockController = ITimelockController( - payable( - vyperDeployer.deployContract( - "src/governance/", - "TimelockController", - args - ) + vyperDeployer.deployContract( + "src/governance/", + "TimelockController", + args ) ); - - counter = new Counter(address(timelockController)); + timelockControllerAddr = address(timelockController); } function testInitialSetup() public { + assertEq(timelockController.DEFAULT_ADMIN_ROLE(), DEFAULT_ADMIN_ROLE); + assertEq(timelockController.PROPOSER_ROLE(), PROPOSER_ROLE); + assertEq(timelockController.EXECUTOR_ROLE(), EXECUTOR_ROLE); + assertEq(timelockController.CANCELLER_ROLE(), CANCELLER_ROLE); + assertEq( + timelockController.IERC721_TOKENRECEIVER_SELECTOR(), + IERC721_TOKENRECEIVER_SELECTOR + ); + assertEq( + timelockController.IERC1155_TOKENRECEIVER_SINGLE_SELECTOR(), + IERC1155_TOKENRECEIVER_SINGLE_SELECTOR + ); assertEq( + timelockController.IERC1155_TOKENRECEIVER_BATCH_SELECTOR(), + IERC1155_TOKENRECEIVER_BATCH_SELECTOR + ); + assertTrue( timelockController.hasRole( timelockController.DEFAULT_ADMIN_ROLE(), - address(this) - ), - true - ); - - checkRoleNotSetForAddresses( - timelockController, - timelockController.DEFAULT_ADMIN_ROLE(), - PROPOSERS + timelockControllerAddr + ) ); - checkRoleNotSetForAddresses( - timelockController, - timelockController.DEFAULT_ADMIN_ROLE(), - EXECUTORS + assertTrue( + timelockController.hasRole( + timelockController.DEFAULT_ADMIN_ROLE(), + self + ) ); - - assertEq( + assertTrue( timelockController.hasRole( timelockController.PROPOSER_ROLE(), PROPOSER_ONE - ), - true + ) ); - assertEq( + assertTrue( timelockController.hasRole( timelockController.PROPOSER_ROLE(), PROPOSER_TWO - ), - true + ) ); - - assertFalse( + assertTrue( timelockController.hasRole( - timelockController.PROPOSER_ROLE(), - ADMIN + timelockController.CANCELLER_ROLE(), + PROPOSER_ONE ) ); - - checkRoleNotSetForAddresses( - timelockController, - timelockController.PROPOSER_ROLE(), - EXECUTORS + assertTrue( + timelockController.hasRole( + timelockController.CANCELLER_ROLE(), + PROPOSER_TWO + ) ); - - assertEq( + assertTrue( timelockController.hasRole( timelockController.EXECUTOR_ROLE(), EXECUTOR_ONE - ), - true + ) ); - assertEq( + assertTrue( timelockController.hasRole( timelockController.EXECUTOR_ROLE(), EXECUTOR_TWO - ), - true + ) ); - assertFalse( - timelockController.hasRole( + assertTrue( + !timelockController.hasRole( + timelockController.PROPOSER_ROLE(), + self + ) + ); + assertTrue( + !timelockController.hasRole( + timelockController.CANCELLER_ROLE(), + self + ) + ); + assertTrue( + !timelockController.hasRole( + timelockController.EXECUTOR_ROLE(), + self + ) + ); + assertTrue( + !timelockController.hasRole( + timelockController.PROPOSER_ROLE(), + timelockControllerAddr + ) + ); + assertTrue( + !timelockController.hasRole( + timelockController.CANCELLER_ROLE(), + timelockControllerAddr + ) + ); + assertTrue( + !timelockController.hasRole( timelockController.EXECUTOR_ROLE(), - ADMIN + timelockControllerAddr ) ); + checkRoleNotSetForAddresses( + timelockController, + timelockController.DEFAULT_ADMIN_ROLE(), + proposers + ); checkRoleNotSetForAddresses( timelockController, timelockController.EXECUTOR_ROLE(), - PROPOSERS + proposers ); - assertEq(timelockController.get_minimum_delay(), MIN_DELAY); - } - - /*////////////////////////////////////////////////////////////// - HELPERS - //////////////////////////////////////////////////////////////*/ - - function checkRoleNotSetForAddresses( - ITimelockController timelock, - bytes32 role, - address[2] storage addresses - ) internal { - for (uint256 i = 0; i < addresses.length; ++i) { - assertFalse(timelock.hasRole(role, addresses[i])); - } - } - - function _laterDelay(uint256 newMinDelay) internal { - vm.startPrank(address(timelockController)); - vm.expectEmit(); - emit ITimelockController.MinimumDelayChange( - timelockController.get_minimum_delay(), - newMinDelay + checkRoleNotSetForAddresses( + timelockController, + timelockController.DEFAULT_ADMIN_ROLE(), + executors ); - timelockController.update_delay(newMinDelay); - vm.stopPrank(); - } - - function _cancelOperation() internal returns (bytes32 operationID) { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT + checkRoleNotSetForAddresses( + timelockController, + timelockController.PROPOSER_ROLE(), + executors + ); + checkRoleNotSetForAddresses( + timelockController, + timelockController.CANCELLER_ROLE(), + executors ); + assertEq(timelockController.get_minimum_delay(), MIN_DELAY); - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + address[] memory proposers_ = new address[](2); + proposers_[0] = proposers[0]; + proposers_[1] = proposers[1]; + address[] memory executors_ = new address[](2); + executors_[0] = executors[0]; + executors_[1] = executors[1]; + bytes memory argsEmptyAdmin = abi.encode( + MIN_DELAY, + proposers_, + executors_, + address(0) + ); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted( + DEFAULT_ADMIN_ROLE, + vm.computeCreateAddress(deployer, vm.getNonce(deployer)), + deployer + ); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(PROPOSER_ROLE, proposers[0], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(CANCELLER_ROLE, proposers[0], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(PROPOSER_ROLE, proposers[1], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(CANCELLER_ROLE, proposers[1], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(EXECUTOR_ROLE, executors[0], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(EXECUTOR_ROLE, executors[1], deployer); + vm.expectEmit(true, true, false, false); + emit ITimelockController.MinimumDelayChange(0, MIN_DELAY); + timelockControllerInitialEventEmptyAdmin = ITimelockController( + vyperDeployer.deployContract( + "src/governance/", + "TimelockController", + argsEmptyAdmin + ) ); - operationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT + timelockControllerInitialEventEmptyAdminAddr = address( + timelockControllerInitialEventEmptyAdmin ); - } - - /*////////////////////////////////////////////////////////////// - OPERATION TESTS - //////////////////////////////////////////////////////////////*/ - - function testOperationComplete() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector + assertEq( + timelockControllerInitialEventEmptyAdmin.DEFAULT_ADMIN_ROLE(), + DEFAULT_ADMIN_ROLE ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT + assertEq( + timelockControllerInitialEventEmptyAdmin.PROPOSER_ROLE(), + PROPOSER_ROLE ); - - assertEq(counter.number(), 0); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY + assertEq( + timelockControllerInitialEventEmptyAdmin.EXECUTOR_ROLE(), + EXECUTOR_ROLE ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + assertEq( + timelockControllerInitialEventEmptyAdmin.CANCELLER_ROLE(), + CANCELLER_ROLE ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - amount, - payload + assertEq( + timelockControllerInitialEventEmptyAdmin + .IERC721_TOKENRECEIVER_SELECTOR(), + IERC721_TOKENRECEIVER_SELECTOR ); - timelockController.execute( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT + assertEq( + timelockControllerInitialEventEmptyAdmin + .IERC1155_TOKENRECEIVER_SINGLE_SELECTOR(), + IERC1155_TOKENRECEIVER_SINGLE_SELECTOR ); - - assertEq(counter.number(), 1); - } - - function testOperationAlreadyScheduled() public { - address target = address(0); - uint256 amount = 0; - bytes memory payload = bytes(""); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT + assertEq( + timelockControllerInitialEventEmptyAdmin + .IERC1155_TOKENRECEIVER_BATCH_SELECTOR(), + IERC1155_TOKENRECEIVER_BATCH_SELECTOR ); - - vm.startPrank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY + assertTrue( + timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.DEFAULT_ADMIN_ROLE(), + timelockControllerInitialEventEmptyAdminAddr + ) ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + assertTrue( + !timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.DEFAULT_ADMIN_ROLE(), + self + ) ); - - vm.expectRevert("TimelockController: operation already scheduled"); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY + assertTrue( + timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.PROPOSER_ROLE(), + PROPOSER_ONE + ) ); - } - - function testOperationInsufficientDelay() public { - address target = address(0); - uint256 amount = 0; - bytes memory payload = bytes(""); - - vm.expectRevert("TimelockController: insufficient delay"); - vm.prank(PROPOSER_ONE); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - 1 + assertTrue( + timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.PROPOSER_ROLE(), + PROPOSER_TWO + ) ); - } - - function testOperationEqualAndGreaterMinDelay() public { - address target = address(0); - uint256 amount = 0; - bytes memory payload = bytes(""); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT + assertTrue( + timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.CANCELLER_ROLE(), + PROPOSER_ONE + ) ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY + assertTrue( + timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.CANCELLER_ROLE(), + PROPOSER_TWO + ) ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, + assertTrue( + timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.EXECUTOR_ROLE(), + EXECUTOR_ONE + ) + ); + assertTrue( + timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.EXECUTOR_ROLE(), + EXECUTOR_TWO + ) + ); + assertTrue( + !timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.PROPOSER_ROLE(), + self + ) + ); + assertTrue( + !timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.CANCELLER_ROLE(), + self + ) + ); + assertTrue( + !timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.EXECUTOR_ROLE(), + self + ) + ); + assertTrue( + !timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.PROPOSER_ROLE(), + timelockControllerInitialEventEmptyAdminAddr + ) + ); + assertTrue( + !timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.CANCELLER_ROLE(), + timelockControllerInitialEventEmptyAdminAddr + ) + ); + assertTrue( + !timelockControllerInitialEventEmptyAdmin.hasRole( + timelockControllerInitialEventEmptyAdmin.EXECUTOR_ROLE(), + timelockControllerInitialEventEmptyAdminAddr + ) + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventEmptyAdmin, + timelockControllerInitialEventEmptyAdmin.DEFAULT_ADMIN_ROLE(), + proposers + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventEmptyAdmin, + timelockControllerInitialEventEmptyAdmin.EXECUTOR_ROLE(), + proposers + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventEmptyAdmin, + timelockControllerInitialEventEmptyAdmin.DEFAULT_ADMIN_ROLE(), + executors + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventEmptyAdmin, + timelockControllerInitialEventEmptyAdmin.PROPOSER_ROLE(), + executors + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventEmptyAdmin, + timelockControllerInitialEventEmptyAdmin.CANCELLER_ROLE(), + executors + ); + assertEq( + timelockControllerInitialEventEmptyAdmin.get_minimum_delay(), MIN_DELAY ); - assertEq(timelockController.is_operation(operationID), true); + bytes memory argsNonEmptyAdmin = abi.encode( + MIN_DELAY, + proposers_, + executors_, + self + ); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted( + DEFAULT_ADMIN_ROLE, + vm.computeCreateAddress(deployer, vm.getNonce(deployer)), + deployer + ); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(DEFAULT_ADMIN_ROLE, self, deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(PROPOSER_ROLE, proposers[0], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(CANCELLER_ROLE, proposers[0], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(PROPOSER_ROLE, proposers[1], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(CANCELLER_ROLE, proposers[1], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(EXECUTOR_ROLE, executors[0], deployer); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleGranted(EXECUTOR_ROLE, executors[1], deployer); + vm.expectEmit(true, true, false, false); + emit ITimelockController.MinimumDelayChange(0, MIN_DELAY); + timelockControllerInitialEventNonEmptyAdmin = ITimelockController( + vyperDeployer.deployContract( + "src/governance/", + "TimelockController", + argsNonEmptyAdmin + ) + ); + timelockControllerInitialEventNonEmptyAdminAddr = address( + timelockControllerInitialEventNonEmptyAdmin + ); - operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - bytes32("1") + assertEq( + timelockControllerInitialEventNonEmptyAdmin.DEFAULT_ADMIN_ROLE(), + DEFAULT_ADMIN_ROLE + ); + assertEq( + timelockControllerInitialEventNonEmptyAdmin.PROPOSER_ROLE(), + PROPOSER_ROLE + ); + assertEq( + timelockControllerInitialEventNonEmptyAdmin.EXECUTOR_ROLE(), + EXECUTOR_ROLE + ); + assertEq( + timelockControllerInitialEventNonEmptyAdmin.CANCELLER_ROLE(), + CANCELLER_ROLE + ); + assertEq( + timelockControllerInitialEventNonEmptyAdmin + .IERC721_TOKENRECEIVER_SELECTOR(), + IERC721_TOKENRECEIVER_SELECTOR + ); + assertEq( + timelockControllerInitialEventNonEmptyAdmin + .IERC1155_TOKENRECEIVER_SINGLE_SELECTOR(), + IERC1155_TOKENRECEIVER_SINGLE_SELECTOR + ); + assertEq( + timelockControllerInitialEventNonEmptyAdmin + .IERC1155_TOKENRECEIVER_BATCH_SELECTOR(), + IERC1155_TOKENRECEIVER_BATCH_SELECTOR + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin + .DEFAULT_ADMIN_ROLE(), + timelockControllerInitialEventNonEmptyAdminAddr + ) + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin + .DEFAULT_ADMIN_ROLE(), + self + ) + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.PROPOSER_ROLE(), + PROPOSER_ONE + ) + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.PROPOSER_ROLE(), + PROPOSER_TWO + ) + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.CANCELLER_ROLE(), + PROPOSER_ONE + ) + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.CANCELLER_ROLE(), + PROPOSER_TWO + ) + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.EXECUTOR_ROLE(), + EXECUTOR_ONE + ) + ); + assertTrue( + timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.EXECUTOR_ROLE(), + EXECUTOR_TWO + ) + ); + assertTrue( + !timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.PROPOSER_ROLE(), + self + ) + ); + assertTrue( + !timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.CANCELLER_ROLE(), + self + ) + ); + assertTrue( + !timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.EXECUTOR_ROLE(), + self + ) + ); + assertTrue( + !timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.PROPOSER_ROLE(), + timelockControllerInitialEventNonEmptyAdminAddr + ) + ); + assertTrue( + !timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.CANCELLER_ROLE(), + timelockControllerInitialEventNonEmptyAdminAddr + ) + ); + assertTrue( + !timelockControllerInitialEventNonEmptyAdmin.hasRole( + timelockControllerInitialEventNonEmptyAdmin.EXECUTOR_ROLE(), + timelockControllerInitialEventNonEmptyAdminAddr + ) + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventNonEmptyAdmin, + timelockControllerInitialEventNonEmptyAdmin.DEFAULT_ADMIN_ROLE(), + proposers + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventNonEmptyAdmin, + timelockControllerInitialEventNonEmptyAdmin.EXECUTOR_ROLE(), + proposers + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventNonEmptyAdmin, + timelockControllerInitialEventNonEmptyAdmin.DEFAULT_ADMIN_ROLE(), + executors + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventNonEmptyAdmin, + timelockControllerInitialEventNonEmptyAdmin.PROPOSER_ROLE(), + executors + ); + checkRoleNotSetForAddresses( + timelockControllerInitialEventNonEmptyAdmin, + timelockControllerInitialEventNonEmptyAdmin.CANCELLER_ROLE(), + executors + ); + assertEq( + timelockControllerInitialEventNonEmptyAdmin.get_minimum_delay(), + MIN_DELAY ); + } - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY + 1 + function testCanReceiveEther() public { + payable(timelockControllerAddr).transfer(0.5 ether); + assertEq(timelockControllerAddr.balance, 0.5 ether); + } + + function testSupportsInterfaceSuccess() public { + assertTrue( + timelockController.supportsInterface(type(IERC165).interfaceId) ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - bytes32("1"), - MIN_DELAY + 1 + assertTrue( + timelockController.supportsInterface( + type(IAccessControl).interfaceId + ) + ); + assertTrue( + timelockController.supportsInterface( + type(IERC1155Receiver).interfaceId + ) + ); + } + + function testSupportsInterfaceSuccessGasCost() public { + uint256 startGas = gasleft(); + timelockController.supportsInterface(type(IERC165).interfaceId); + uint256 gasUsed = startGas - gasleft(); + assertTrue( + gasUsed <= 30_000 && + timelockController.supportsInterface(type(IERC165).interfaceId) ); + } - assertEq(timelockController.is_operation(operationID), true); + function testSupportsInterfaceInvalidInterfaceId() public { + assertTrue(!timelockController.supportsInterface(0x0011bbff)); } - function testOperationMinDelayUpdate() public { - address target = address(0); - uint256 amount = 0; - bytes memory payload = bytes(""); + function testSupportsInterfaceInvalidInterfaceIdGasCost() public { + uint256 startGas = gasleft(); + timelockController.supportsInterface(0x0011bbff); + uint256 gasUsed = startGas - gasleft(); + assertTrue( + gasUsed <= 30_000 && + !timelockController.supportsInterface(0x0011bbff) + ); + } - bytes32 operationID = timelockController.hash_operation( + function testScheduleAndExecuteWithEmptySalt() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( target, amount, payload, NO_PREDECESSOR, EMPTY_SALT ); + assertEq(vm.load(target, slot), bytes32(uint256(0))); + assertEq(timelockController.get_timestamp(operationId), 0); - vm.prank(PROPOSER_ONE); - vm.expectEmit(); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); emit ITimelockController.CallScheduled( - operationID, + operationId, 0, target, amount, @@ -440,39 +683,59 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - - uint256 operationTimestampBefore = timelockController.get_timestamp( - operationID + // solhint-disable-next-line not-rely-on-time + assertEq( + timelockController.get_timestamp(operationId), + block.timestamp + MIN_DELAY ); + vm.stopPrank(); - // Set a new delay value - vm.prank(address(timelockController)); - timelockController.update_delay(MIN_DELAY + 31 days); - - // New delay value should only apply on future operations, not existing ones - uint256 operationTimestampAfter = timelockController.get_timestamp( - operationID + // solhint-disable-next-line not-rely-on-time + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + target, + amount, + payload ); - assertEq(operationTimestampAfter, operationTimestampBefore); + timelockController.execute( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(vm.load(target, slot), value); + assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); + vm.stopPrank(); } - function testOperationOperationIsNotReady() public { - address target = address(0); + function testScheduleAndExecuteWithNonEmptySalt() public { uint256 amount = 0; - bytes memory payload = bytes(""); - - bytes32 operationID = timelockController.hash_operation( + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( target, amount, payload, NO_PREDECESSOR, - EMPTY_SALT + SALT ); + assertEq(vm.load(target, slot), bytes32(uint256(0))); + assertEq(timelockController.get_timestamp(operationId), 0); - vm.prank(PROPOSER_ONE); - vm.expectEmit(); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); emit ITimelockController.CallScheduled( - operationID, + operationId, 0, target, amount, @@ -480,47 +743,60 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, MIN_DELAY ); + vm.expectEmit(true, false, false, true); + emit ITimelockController.CallSalt(operationId, SALT); timelockController.schedule( target, amount, payload, NO_PREDECESSOR, - EMPTY_SALT, + SALT, MIN_DELAY ); + // solhint-disable-next-line not-rely-on-time + assertEq( + timelockController.get_timestamp(operationId), + block.timestamp + MIN_DELAY + ); + vm.stopPrank(); - vm.warp(block.timestamp + MIN_DELAY - 2 days); - - vm.expectRevert("TimelockController: operation is not ready"); - vm.prank(EXECUTOR_ONE); + // solhint-disable-next-line not-rely-on-time + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + target, + amount, + payload + ); timelockController.execute( target, amount, payload, NO_PREDECESSOR, - EMPTY_SALT + SALT ); + assertEq(vm.load(target, slot), value); + assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); + vm.stopPrank(); } - function testOperationPredecessorNotExecuted() public { - address target = address(counter); + function testOperationAlreadyScheduled() public { uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( + bytes memory payload = new bytes(0); + bytes32 operationId = timelockController.hash_operation( target, amount, payload, NO_PREDECESSOR, EMPTY_SALT ); - vm.startPrank(PROPOSER_ONE); vm.expectEmit(); emit ITimelockController.CallScheduled( - operationID, + operationId, 0, target, amount, @@ -536,3208 +812,3321 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - - bytes32 operationID2 = timelockController.hash_operation( - target, - amount, - payload, - operationID, - EMPTY_SALT - ); - - // Schedule dependent job - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID2, - 0, - target, - amount, - payload, - operationID, - MIN_DELAY - ); + vm.expectRevert("TimelockController: operation already scheduled"); timelockController.schedule( target, amount, payload, - operationID, + NO_PREDECESSOR, EMPTY_SALT, MIN_DELAY ); vm.stopPrank(); + } - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute( - target, - amount, - payload, - operationID, - EMPTY_SALT - ); - } - - function testOperationPredecessorNotScheduled() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID1 = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bytes32 operationID2 = timelockController.hash_operation( - target, - amount, - payload, - operationID1, - EMPTY_SALT - ); - - // Schedule dependent job - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID2, - 0, - target, - amount, - payload, - operationID1, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - operationID1, - EMPTY_SALT, - MIN_DELAY - ); - vm.stopPrank(); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute( - target, - amount, - payload, - operationID1, - EMPTY_SALT - ); - } - - function testOperationPredecessorInvalid() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - // Prepare invalid predecessor - bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - invalidPredecessor, - EMPTY_SALT - ); - - // Schedule dependent job - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - invalidPredecessor, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - invalidPredecessor, - EMPTY_SALT, - MIN_DELAY - ); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute( - target, - amount, - payload, - invalidPredecessor, - EMPTY_SALT - ); - } - - function testOperationTargetRevert() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.mockRevert.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - // Schedule a job where one target will revert - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY + 2 days); - - vm.expectRevert("Transaction reverted"); - vm.prank(EXECUTOR_ONE); - timelockController.execute( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testOperationPredecessorMultipleNotExecuted() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - // Schedule predecessor job - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - payload = abi.encodeWithSelector(Counter.setNumber.selector, 1); - - // Schedule dependent job - vm.prank(PROPOSER_ONE); - timelockController.schedule( - target, - amount, - payload, - operationID, - EMPTY_SALT, - MIN_DELAY - ); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute( - target, - amount, - payload, - operationID, - EMPTY_SALT - ); - } - - function testOperationCancelFinished() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY + 1); - - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - amount, - payload - ); - timelockController.execute( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - vm.prank(PROPOSER_ONE); - vm.expectRevert("TimelockController: operation cannot be cancelled"); - timelockController.cancel(operationID); - } - - function testOperationPendingIfNotYetExecuted() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - bool is_operation_pending = timelockController.is_operation_pending( - operationID - ); - assertEq(is_operation_pending, true); - } - - function testOperationPendingIfExecuted() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - amount, - payload - ); - timelockController.execute( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bool is_operation_pending = timelockController.is_operation_pending( - operationID - ); - assertEq(is_operation_pending, false); - } - - function testOperationReadyOnTheExecutionTime() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - bool is_operation_ready = timelockController.is_operation_ready( - operationID - ); - assertEq(is_operation_ready, true); - } - - function testOperationReadyAfterTheExecutionTime() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY + 1 days); - - bool is_operation_ready = timelockController.is_operation_ready( - operationID - ); - assertEq(is_operation_ready, true); - } - - function testOperationReadyBeforeTheExecutionTime() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY - 1 days); - - bool is_operation_ready = timelockController.is_operation_ready( - operationID - ); - assertEq(is_operation_ready, false); - } - - function testOperationHasBeenExecuted() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - amount, - payload - ); - timelockController.execute( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bool is_operation_ready = timelockController.is_operation_ready( - operationID - ); - assertEq(is_operation_ready, false); - - bool is_operation_done = timelockController.is_operation_done( - operationID - ); - assertEq(is_operation_done, true); - } - - function testOperationHasNotBeenExecuted() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - bool is_operation_done = timelockController.is_operation_done( - operationID - ); - assertEq(is_operation_done, false); - } - - function testOperationTimestampHasNotBeenExecuted() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - operationID - ); - assertEq(operationTimestamp, block.timestamp + MIN_DELAY); - } - - function testOperationTimestampHasBeenExecuted() public { - address target = address(counter); - uint256 amount = 0; - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - amount, - payload - ); - timelockController.execute( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - operationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - } - - function testFuzzOperationValue(uint256 amount) public { - address target = address(counter); - bytes memory payload = abi.encodeWithSelector( - Counter.increment.selector - ); - - bytes32 operationID = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - deal(address(timelockController), amount); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationID, - 0, - target, - amount, - payload, - NO_PREDECESSOR, - MIN_DELAY - ); - timelockController.schedule( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - vm.expectEmit(); - emit ITimelockController.CallExecuted( - operationID, - 0, - target, - amount, - payload - ); - timelockController.execute( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - operationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(address(counter).balance, amount); - } - - function testOperationERC1155() public { - ERC1155Mock erc1155 = new ERC1155Mock(""); - erc1155.mint(address(timelockController), 1, 1, bytes("")); - - assertEq(erc1155.balanceOf(address(timelockController), 1), 1); - - address[] memory targets = new address[](1); - targets[0] = address(erc1155); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector( - ERC1155Mock.burn.selector, - address(timelockController), - 1, - 1 - ); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(erc1155.balanceOf(address(timelockController), 1), 0); - } - - function testOperationERC721() public { - ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); - erc721.mint(address(timelockController), 1); - - assertEq(erc721.balanceOf(address(timelockController)), 1); - - address[] memory targets = new address[](1); - targets[0] = address(erc721); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(erc721.balanceOf(address(timelockController)), 0); - } - - /*////////////////////////////////////////////////////////////// - BATCH TESTS - //////////////////////////////////////////////////////////////*/ - - function testBatchComplete() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - assertEq(counter.number(), 0); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - assertEq(counter.number(), 1); - } - - function testBatchOperationAlreadyScheduled() public { - address[] memory targets = new address[](1); - targets[0] = address(0); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = bytes(""); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.startPrank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.expectRevert("TimelockController: operation already scheduled"); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - } - - function testBatchInsufficientDelay() public { - address[] memory targets = new address[](1); - targets[0] = address(0); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = bytes(""); - - vm.expectRevert("TimelockController: insufficient delay"); - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - 1 - ); - } - - function testBatchEqualAndGreaterMinDelay() public { - address[] memory targets = new address[](1); - targets[0] = address(0); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = bytes(""); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - assertEq(timelockController.is_operation(batchedOperationID), true); - - batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - bytes32("1") - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY + 1 - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - bytes32("1"), - MIN_DELAY + 1 - ); - - assertEq(timelockController.is_operation(batchedOperationID), true); - } - - function testBatchMinDelayUpdate() public { - address[] memory targets = new address[](1); - targets[0] = address(0); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = bytes(""); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - uint256 operationTimestampBefore = timelockController.get_timestamp( - batchedOperationID - ); - - // Set a new delay value - vm.prank(address(timelockController)); - timelockController.update_delay(MIN_DELAY + 31 days); - - // New delay value should only apply on future operations, not existing ones - uint256 operationTimestampAfter = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestampAfter, operationTimestampBefore); - } - - function testBatchOperationIsNotReady() public { - address[] memory targets = new address[](1); - targets[0] = address(0); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = bytes(""); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY - 2 days); - - vm.expectRevert("TimelockController: operation is not ready"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testBatchPredecessorNotExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.startPrank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - bytes32 batchedOperationID2 = timelockController.hash_operation_batch( - targets, - values, - payloads, - batchedOperationID, - EMPTY_SALT - ); - - // Schedule dependent job - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID2, - i, - targets[i], - values[i], - payloads[i], - batchedOperationID, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - batchedOperationID, - EMPTY_SALT, - MIN_DELAY - ); - vm.stopPrank(); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - batchedOperationID, - EMPTY_SALT - ); - } - - function testBatchPredecessorNotScheduled() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - vm.startPrank(PROPOSER_ONE); - - // Prepare predecessor job - bytes32 operationOneID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bytes32 operationOneID2 = timelockController.hash_operation_batch( - targets, - values, - payloads, - operationOneID, - EMPTY_SALT - ); - - // Schedule dependent job - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - operationOneID2, - i, - targets[i], - values[i], - payloads[i], - operationOneID, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - operationOneID, - EMPTY_SALT, - MIN_DELAY - ); - vm.stopPrank(); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - operationOneID, - EMPTY_SALT - ); - } - - function testBatchPredecessorInvalid() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // Prepare invalid predecessor - bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - invalidPredecessor, - EMPTY_SALT - ); - - // Schedule dependent job - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - invalidPredecessor, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - invalidPredecessor, - EMPTY_SALT, - MIN_DELAY - ); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - invalidPredecessor, - EMPTY_SALT - ); - } - - function testBatchTargetRevert() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - // Schedule a job where one target will revert - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("Transaction reverted"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testBatchPredecessorMultipleNotExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - // Schedule predecessor job - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); - - // Schedule dependent job - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( - targets, - values, - payloads, - batchedOperationID, - EMPTY_SALT, - MIN_DELAY - ); - - // Check that executing the dependent job reverts - vm.warp(block.timestamp + MIN_DELAY + 2 days); - vm.expectRevert("TimelockController: missing dependency"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - batchedOperationID, - EMPTY_SALT - ); - } - - function testBatchCancelFinished() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY + 1); - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - vm.prank(PROPOSER_ONE); - vm.expectRevert("TimelockController: operation cannot be cancelled"); - timelockController.cancel(batchedOperationID); - } - - function testBatchPendingIfNotYetExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - bool is_operation_pending = timelockController.is_operation_pending( - batchedOperationID - ); - assertEq(is_operation_pending, true); - } - - function testBatchPendingIfExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bool is_operation_pending = timelockController.is_operation_pending( - batchedOperationID - ); - assertEq(is_operation_pending, false); - } - - function testBatchReadyOnTheExecutionTime() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID - ); - assertEq(is_operation_ready, true); - } - - function testBatchReadyAfterTheExecutionTime() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY + 1 days); - - bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID - ); - assertEq(is_operation_ready, true); - } - - function testBatchReadyBeforeTheExecutionTime() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY - 1 days); - - bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID - ); - assertEq(is_operation_ready, false); - } - - function testBatchHasBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - bool is_operation_ready = timelockController.is_operation_ready( - batchedOperationID - ); - assertEq(is_operation_ready, false); - - bool is_operation_done = timelockController.is_operation_done( - batchedOperationID - ); - assertEq(is_operation_done, true); - } - - function testBatchHasNotBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - bool is_operation_done = timelockController.is_operation_done( - batchedOperationID - ); - assertEq(is_operation_done, false); - } - - function testBatchTimestampHasNotBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestamp, block.timestamp + MIN_DELAY); - } - - function testBatchTimestampHasBeenExecuted() public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - } - - function testFuzzBatchValue(uint256 amount) public { - address[] memory targets = new address[](1); - targets[0] = address(counter); - - uint256[] memory values = new uint256[](1); - values[0] = amount; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - deal(address(timelockController), amount); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(address(counter).balance, values[0]); - } - - function testBatchERC1155() public { - ERC1155Mock erc1155 = new ERC1155Mock(""); - erc1155.mint(address(timelockController), 1, 1, bytes("")); - - assertEq(erc1155.balanceOf(address(timelockController), 1), 1); - - address[] memory targets = new address[](1); - targets[0] = address(erc1155); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector( - ERC1155Mock.burn.selector, - address(timelockController), - 1, - 1 - ); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(erc1155.balanceOf(address(timelockController), 1), 0); - } - - function testBatchERC721() public { - ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); - erc721.mint(address(timelockController), 1); - - assertEq(erc721.balanceOf(address(timelockController)), 1); - - address[] memory targets = new address[](1); - targets[0] = address(erc721); - - uint256[] memory values = new uint256[](1); - values[0] = 0; - - bytes[] memory payloads = new bytes[](1); - payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); - - bytes32 batchedOperationID = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.prank(PROPOSER_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallScheduled( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i], - NO_PREDECESSOR, - MIN_DELAY - ); - } - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); - for (uint256 i = 0; i < targets.length; ++i) { - vm.expectEmit(); - emit ITimelockController.CallExecuted( - batchedOperationID, - i, - targets[i], - values[i], - payloads[i] - ); - } - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - uint256 operationTimestamp = timelockController.get_timestamp( - batchedOperationID - ); - assertEq(operationTimestamp, DONE_TIMESTAMP); - assertEq(erc721.balanceOf(address(timelockController)), 0); - } - - /*////////////////////////////////////////////////////////////// - SANITY CHECKS TESTS - //////////////////////////////////////////////////////////////*/ - - function testReturnsLaterMinDelayForCalls() public { - uint256 newMinDelay = 31 days; - _laterDelay(newMinDelay); - uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, newMinDelay); - } - - function testCanReceiveEther() public { - vm.prank(ADMIN); - payable(address(timelockController)).transfer(0.5 ether); - assertEq(address(timelockController).balance, 0.5 ether); - } - - function testInvalidOperation() public { - bool is_operation = timelockController.is_operation(bytes32("non-op")); - assertEq(is_operation, false); - } - - // ERC165 `supportsInterface` - - function testSupportsInterfaceSuccess() public { - assertTrue( - timelockController.supportsInterface(type(IERC165).interfaceId) - ); - assertTrue( - timelockController.supportsInterface( - type(IAccessControl).interfaceId - ) - ); - assertTrue( - timelockController.supportsInterface( - type(IERC1155Receiver).interfaceId - ) - ); - } - - function testSupportsInterfaceSuccessGasCost() public { - uint256 startGas = gasleft(); - timelockController.supportsInterface(type(IERC165).interfaceId); - uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && - timelockController.supportsInterface(type(IERC165).interfaceId) - ); - } - - function testSupportsInterfaceInvalidInterfaceId() public { - assertTrue(!timelockController.supportsInterface(0x0011bbff)); - } - - function testSupportsInterfaceInvalidInterfaceIdGasCost() public { - uint256 startGas = gasleft(); - timelockController.supportsInterface(0x0011bbff); - uint256 gasUsed = startGas - gasleft(); - assertTrue( - gasUsed <= 30_000 && - !timelockController.supportsInterface(0x0011bbff) - ); - } - - // Hash calculation - function testHashOperationBatch() public { - address[] memory targets = new address[](2); - targets[0] = address(this); - targets[1] = address(this); - - uint256[] memory values = new uint256[](2); - values[0] = 0; - values[1] = 1; - - bytes[] memory payloads = new bytes[](2); - payloads[0] = abi.encodeWithSelector( - this.testHashOperationBatch.selector - ); - payloads[1] = abi.encodeWithSelector( - this.testHashOperationBatch.selector - ); - - bytes32 hashedOperation = timelockController.hash_operation_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - bytes32 expectedHash = keccak256( - abi.encode(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT) - ); - assertEq(hashedOperation, expectedHash); - } - - function testHashOperation() public { - address target = address(this); - uint256 amount = 1; - bytes memory payload = abi.encodeWithSelector( - this.testHashOperationBatch.selector - ); - - bytes32 hashedOperation = timelockController.hash_operation( - target, - amount, - payload, - NO_PREDECESSOR, - EMPTY_SALT - ); - bytes32 expectedHash = keccak256( - abi.encode(target, amount, payload, NO_PREDECESSOR, EMPTY_SALT) - ); - assertEq(hashedOperation, expectedHash); - } - - // TODO: Add NFTs tests - - /*////////////////////////////////////////////////////////////// - PERMISSION TESTS - //////////////////////////////////////////////////////////////*/ - - // Timelock - - function testRevertWhenNotTimelock() public { - vm.expectRevert("TimelockController: caller must be timelock"); - vm.prank(STRANGER); - timelockController.update_delay(3 days); - } - - // Admin - - function testAdminCantBatchSchedule() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - } - - function testAdminCantSchedule() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.schedule( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - } - - function testAdminCantBatchExecute() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testAdminCantExecute() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.execute( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testAdminCantCancel() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(ADMIN); - timelockController.cancel(EMPTY_SALT); - } - - // Proposer - - function testProposerCanBatchSchedule() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.prank(PROPOSER_ONE); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.prank(PROPOSER_TWO); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - bytes32("1"), - MIN_DELAY - ); - } - - function testProposerCanSchedule() public { - vm.prank(PROPOSER_ONE); - timelockController.schedule( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.prank(PROPOSER_TWO); - timelockController.schedule( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - bytes32("1"), - MIN_DELAY - ); - } - - function testProposerCantBatchExecute() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(PROPOSER_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(PROPOSER_TWO); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - bytes32("1") - ); - } - - function testProposerCantExecute() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(PROPOSER_ONE); - timelockController.execute( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(PROPOSER_TWO); - timelockController.execute( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - bytes32("1") - ); - } - - function testProposerCanCancel() public { - vm.expectRevert("TimelockController: operation cannot be cancelled"); + function testOperationInsufficientDelay() public { + vm.expectRevert("TimelockController: insufficient delay"); vm.prank(PROPOSER_ONE); - timelockController.cancel(EMPTY_SALT); - - vm.expectRevert("TimelockController: operation cannot be cancelled"); - vm.prank(PROPOSER_TWO); - timelockController.cancel(EMPTY_SALT); - } - - // Executor - - function testExecutorCantBatchSchedule() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(EXECUTOR_ONE); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(EXECUTOR_TWO); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - bytes32("1"), - MIN_DELAY - ); - } - - function testExecutorCantSchedule() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(EXECUTOR_ONE); - timelockController.schedule( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(EXECUTOR_TWO); - timelockController.schedule( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - bytes32("1"), - MIN_DELAY - ); - } - - function testExecutorCanBatchExecute() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.expectRevert("TimelockController: operation is not ready"); - vm.prank(EXECUTOR_ONE); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.expectRevert("TimelockController: operation is not ready"); - vm.prank(EXECUTOR_TWO); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - bytes32("1") - ); - } - - function testExecutorCanExecute() public { - vm.expectRevert("TimelockController: operation is not ready"); - vm.prank(EXECUTOR_ONE); - timelockController.execute( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - EMPTY_SALT - ); - - vm.expectRevert("TimelockController: operation is not ready"); - vm.prank(EXECUTOR_TWO); - timelockController.execute( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - bytes32("1") - ); - } - - function testExecutorCantCancel() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(EXECUTOR_ONE); - timelockController.cancel(EMPTY_SALT); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(EXECUTOR_TWO); - timelockController.cancel(EMPTY_SALT); - } - - // Stanger - - function testStrangerCantBatchSchedule() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.schedule_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT, - MIN_DELAY - ); - } - - function testStrangerCantSchedule() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); timelockController.schedule( - address(0), + target, 0, - bytes(""), + new bytes(0), NO_PREDECESSOR, EMPTY_SALT, - MIN_DELAY - ); - } - - function testStrangerCantBatchExecute() public { - address[] memory targets = new address[](0); - uint256[] memory values = new uint256[](0); - bytes[] memory payloads = new bytes[](0); - - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.execute_batch( - targets, - values, - payloads, - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testStrangerCantExecute() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.execute( - address(0), - 0, - bytes(""), - NO_PREDECESSOR, - EMPTY_SALT - ); - } - - function testStrangerCantCancel() public { - vm.expectRevert("AccessControl: account is missing role"); - vm.prank(STRANGER); - timelockController.cancel(EMPTY_SALT); - } - - // TODO: Move this somewhere in correct place - function testCancellerCanCancelOperation() public { - bytes32 operationID = _cancelOperation(); - - vm.prank(PROPOSER_ONE); - vm.expectEmit(); - emit ITimelockController.Cancelled(operationID); - timelockController.cancel(operationID); - assertFalse(timelockController.is_operation(operationID)); - } -} - -contract ERC1155Mock is ERC1155 { - constructor(string memory uri) ERC1155(uri) {} - - function mint( - address to, - uint256 id, - uint256 value, - bytes memory data - ) external { - _mint(to, id, value, data); - } - - function burn(address from, uint256 id, uint256 value) external { - _burn(from, id, value); - } -} - -contract ERC721Mock is ERC721 { - constructor( - string memory name, - string memory symbol - ) ERC721(name, symbol) {} - - function mint(address to, uint256 tokenId) external { - _mint(to, tokenId); - } - - function burn(uint256 tokenId) external { - _burn(tokenId); - } -} - -contract Counter { - address private timelock; - uint256 public number; - - constructor(address _timelock) { - timelock = _timelock; - } - - modifier onlyTimelock() { - require(msg.sender == timelock, "Not timelock controller"); - _; - } - - function setNumber(uint256 newNumber) external onlyTimelock { - number = newNumber; - } - - function increment() external payable onlyTimelock { - number++; - } - - function mockRevert() external pure { - revert("Transaction reverted"); - } -} - -contract TimelockControllerInvariants is Test { - VyperDeployer private vyperDeployer = new VyperDeployer(); - - ITimelockController private timelockController; - TimelockControllerHandler private timelockControllerHandler; - - function setUp() public { - address[] memory proposers = new address[](1); - proposers[0] = address(this); - - address[] memory executors = new address[](1); - executors[0] = address(this); - - uint256 minDelay = 2 days; - - bytes memory args = abi.encode( - minDelay, - proposers, - executors, - address(this) - ); - timelockController = ITimelockController( - payable( - vyperDeployer.deployContract( - "src/governance/", - "TimelockController", - args - ) - ) - ); - - timelockControllerHandler = new TimelockControllerHandler( - timelockController, - minDelay, - proposers, - executors, - address(this) - ); - - // Select the selectors to use for fuzzing. - bytes4[] memory selectors = new bytes4[](3); - selectors[0] = TimelockControllerHandler.schedule.selector; - selectors[1] = TimelockControllerHandler.execute.selector; - selectors[2] = TimelockControllerHandler.cancel.selector; - - // Set the target selector. - targetSelector( - FuzzSelector({ - addr: address(timelockControllerHandler), - selectors: selectors - }) - ); - - // Set the target contract. - targetContract(address(timelockControllerHandler)); - } - - // Number of pending transactions cannot exceed executed transactions - function invariantExecutedLessThanOrEqualToPending() public { - assertLe( - timelockControllerHandler.execute_count(), - timelockControllerHandler.schedule_count() - ); - } - - // Number of proposals executed must match the count number. - function invariantProposalsExecutedMatchCount() public { - assertEq( - timelockControllerHandler.execute_count(), - timelockControllerHandler.counter() - ); - } - - // Proposals can only be scheduled and executed once - function invariantOnceProposalExecution() public { - uint256[] memory executed = timelockControllerHandler.getExecuted(); - // Loop over all executed proposals. - for (uint256 i = 0; i < executed.length; ++i) { - // Check that the executed proposal cannot be executed again. - vm.expectRevert("TimelockController: operation is not ready"); - timelockController.execute( - address(timelockControllerHandler), - 0, - abi.encodeWithSelector( - TimelockControllerHandler.increment.selector - ), - bytes32(""), - bytes32(executed[i]) - ); - } - } - - // Sum of number of executed proposals and cancelled proposals must be less or equal to the amount of proposals scheduled. - function invariantSumOfProposals() public { - assertLe( - timelockControllerHandler.cancel_count() + - timelockControllerHandler.execute_count(), - timelockControllerHandler.schedule_count() + MIN_DELAY - 1 ); } - // Executed proposals cannot be cancelled - function invariantExecutedProposalCancellation() public { - uint256[] memory executed = timelockControllerHandler.getExecuted(); - // Loop over all executed proposals. - for (uint256 i = 0; i < executed.length; ++i) { - // Check that the executed proposal cannot be cancelled. - vm.expectRevert( - "TimelockController: operation cannot be cancelled" - ); - timelockController.cancel(bytes32(executed[i])); - } - } - - // Executing a proposal that has been cancelled is not possible - function invariantExecutingCancelledProposal() public { - uint256[] memory cancelled = timelockControllerHandler.getCancelled(); - // Loop over all cancelled proposals. - for (uint256 i = 0; i < cancelled.length; ++i) { - // Check that the cancelled proposal cannot be executed. - vm.expectRevert("TimelockController: operation is not ready"); - timelockController.execute( - address(timelockControllerHandler), - 0, - abi.encodeWithSelector( - TimelockControllerHandler.increment.selector - ), - bytes32(""), - bytes32(cancelled[i]) - ); - } - } - - // Executing a proposal that is not ready is not possible - function invariantExecutingNotReadyProposal() public { - uint256[] memory pending = timelockControllerHandler.getPending(); - // Loop over all pending proposals. - for (uint256 i = 0; i < pending.length; ++i) { - // Check that the pending proposal cannot be executed. - vm.expectRevert("TimelockController: operation is not ready"); - timelockController.execute( - address(timelockControllerHandler), - 0, - abi.encodeWithSelector( - TimelockControllerHandler.increment.selector - ), - bytes32(""), - bytes32(pending[i]) - ); - } - } + // function testOperationEqualAndGreaterMinDelay() public { + // address target = address(0); + // uint256 amount = 0; + // bytes memory payload = bytes(""); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // assertEq(timelockController.is_operation(operationID), true); + + // operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // bytes32("1") + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + 1 + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // bytes32("1"), + // MIN_DELAY + 1 + // ); + + // assertEq(timelockController.is_operation(operationID), true); + // } + + // function testOperationMinDelayUpdate() public { + // address target = address(0); + // uint256 amount = 0; + // bytes memory payload = bytes(""); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // uint256 operationTimestampBefore = timelockController.get_timestamp( + // operationID + // ); + + // // Set a new delay value + // vm.prank(address(timelockController)); + // timelockController.update_delay(MIN_DELAY + 31 days); + + // // New delay value should only apply on future operations, not existing ones + // uint256 operationTimestampAfter = timelockController.get_timestamp( + // operationID + // ); + // assertEq(operationTimestampAfter, operationTimestampBefore); + // } + + // function testOperationOperationIsNotReady() public { + // address target = address(0); + // uint256 amount = 0; + // bytes memory payload = bytes(""); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY - 2 days); + + // vm.expectRevert("TimelockController: operation is not ready"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testOperationPredecessorNotExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.startPrank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // bytes32 operationID2 = timelockController.hash_operation( + // target, + // amount, + // payload, + // operationID, + // EMPTY_SALT + // ); + + // // Schedule dependent job + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID2, + // 0, + // target, + // amount, + // payload, + // operationID, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // operationID, + // EMPTY_SALT, + // MIN_DELAY + // ); + // vm.stopPrank(); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute( + // target, + // amount, + // payload, + // operationID, + // EMPTY_SALT + // ); + // } + + // function testOperationPredecessorNotScheduled() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID1 = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // bytes32 operationID2 = timelockController.hash_operation( + // target, + // amount, + // payload, + // operationID1, + // EMPTY_SALT + // ); + + // // Schedule dependent job + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID2, + // 0, + // target, + // amount, + // payload, + // operationID1, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // operationID1, + // EMPTY_SALT, + // MIN_DELAY + // ); + // vm.stopPrank(); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute( + // target, + // amount, + // payload, + // operationID1, + // EMPTY_SALT + // ); + // } + + // function testOperationPredecessorInvalid() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // // Prepare invalid predecessor + // bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // invalidPredecessor, + // EMPTY_SALT + // ); + + // // Schedule dependent job + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // invalidPredecessor, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // invalidPredecessor, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute( + // target, + // amount, + // payload, + // invalidPredecessor, + // EMPTY_SALT + // ); + // } + + // function testOperationTargetRevert() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.mockRevert.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // // Schedule a job where one target will revert + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + + // vm.expectRevert("Transaction reverted"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testOperationPredecessorMultipleNotExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // // Schedule predecessor job + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // payload = abi.encodeWithSelector(Counter.setNumber.selector, 1); + + // // Schedule dependent job + // vm.prank(PROPOSER_ONE); + // timelockController.schedule( + // target, + // amount, + // payload, + // operationID, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute( + // target, + // amount, + // payload, + // operationID, + // EMPTY_SALT + // ); + // } + + // function testOperationCancelFinished() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY + 1); + + // vm.prank(EXECUTOR_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // operationID, + // 0, + // target, + // amount, + // payload + // ); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // vm.prank(PROPOSER_ONE); + // vm.expectRevert("TimelockController: operation cannot be cancelled"); + // timelockController.cancel(operationID); + // } + + // function testOperationPendingIfNotYetExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // bool is_operation_pending = timelockController.is_operation_pending( + // operationID + // ); + // assertEq(is_operation_pending, true); + // } + + // function testOperationPendingIfExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // operationID, + // 0, + // target, + // amount, + // payload + // ); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // bool is_operation_pending = timelockController.is_operation_pending( + // operationID + // ); + // assertEq(is_operation_pending, false); + // } + + // function testOperationReadyOnTheExecutionTime() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // bool is_operation_ready = timelockController.is_operation_ready( + // operationID + // ); + // assertEq(is_operation_ready, true); + // } + + // function testOperationReadyAfterTheExecutionTime() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY + 1 days); + + // bool is_operation_ready = timelockController.is_operation_ready( + // operationID + // ); + // assertEq(is_operation_ready, true); + // } + + // function testOperationReadyBeforeTheExecutionTime() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY - 1 days); + + // bool is_operation_ready = timelockController.is_operation_ready( + // operationID + // ); + // assertEq(is_operation_ready, false); + // } + + // function testOperationHasBeenExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + // vm.prank(EXECUTOR_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // operationID, + // 0, + // target, + // amount, + // payload + // ); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // bool is_operation_ready = timelockController.is_operation_ready( + // operationID + // ); + // assertEq(is_operation_ready, false); + + // bool is_operation_done = timelockController.is_operation_done( + // operationID + // ); + // assertEq(is_operation_done, true); + // } + + // function testOperationHasNotBeenExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // bool is_operation_done = timelockController.is_operation_done( + // operationID + // ); + // assertEq(is_operation_done, false); + // } + + // function testOperationTimestampHasNotBeenExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // operationID + // ); + // assertEq(operationTimestamp, block.timestamp + MIN_DELAY); + // } + + // function testOperationTimestampHasBeenExecuted() public { + // address target = address(counter); + // uint256 amount = 0; + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + // vm.prank(EXECUTOR_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // operationID, + // 0, + // target, + // amount, + // payload + // ); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // operationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // } + + // function testFuzzOperationValue(uint256 amount) public { + // address target = address(counter); + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationID = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // deal(address(timelockController), amount); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationID, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // operationID, + // 0, + // target, + // amount, + // payload + // ); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // operationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(address(counter).balance, amount); + // } + + // function testOperationERC1155() public { + // ERC1155Mock erc1155 = new ERC1155Mock(""); + // erc1155.mint(address(timelockController), 1, 1, bytes("")); + + // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc1155); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector( + // ERC1155Mock.burn.selector, + // address(timelockController), + // 1, + // 1 + // ); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); + // } + + // function testOperationERC721() public { + // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); + // erc721.mint(address(timelockController), 1); + + // assertEq(erc721.balanceOf(address(timelockController)), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc721); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc721.balanceOf(address(timelockController)), 0); + // } + + // /*////////////////////////////////////////////////////////////// + // BATCH TESTS + // //////////////////////////////////////////////////////////////*/ + + // function testBatchComplete() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // assertEq(counter.number(), 0); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // assertEq(counter.number(), 1); + // } + + // function testBatchOperationAlreadyScheduled() public { + // address[] memory targets = new address[](1); + // targets[0] = address(0); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = bytes(""); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.startPrank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.expectRevert("TimelockController: operation already scheduled"); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + // } + + // function testBatchInsufficientDelay() public { + // address[] memory targets = new address[](1); + // targets[0] = address(0); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = bytes(""); + + // vm.expectRevert("TimelockController: insufficient delay"); + // vm.prank(PROPOSER_ONE); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY - 1 + // ); + // } + + // function testBatchEqualAndGreaterMinDelay() public { + // address[] memory targets = new address[](1); + // targets[0] = address(0); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = bytes(""); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // assertEq(timelockController.is_operation(batchedOperationID), true); + + // batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // bytes32("1") + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + 1 + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // bytes32("1"), + // MIN_DELAY + 1 + // ); + + // assertEq(timelockController.is_operation(batchedOperationID), true); + // } + + // function testBatchMinDelayUpdate() public { + // address[] memory targets = new address[](1); + // targets[0] = address(0); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = bytes(""); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // uint256 operationTimestampBefore = timelockController.get_timestamp( + // batchedOperationID + // ); + + // // Set a new delay value + // vm.prank(address(timelockController)); + // timelockController.update_delay(MIN_DELAY + 31 days); + + // // New delay value should only apply on future operations, not existing ones + // uint256 operationTimestampAfter = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestampAfter, operationTimestampBefore); + // } + + // function testBatchOperationIsNotReady() public { + // address[] memory targets = new address[](1); + // targets[0] = address(0); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = bytes(""); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY - 2 days); + + // vm.expectRevert("TimelockController: operation is not ready"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testBatchPredecessorNotExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.startPrank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // bytes32 batchedOperationID2 = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // batchedOperationID, + // EMPTY_SALT + // ); + + // // Schedule dependent job + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID2, + // i, + // targets[i], + // values[i], + // payloads[i], + // batchedOperationID, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // batchedOperationID, + // EMPTY_SALT, + // MIN_DELAY + // ); + // vm.stopPrank(); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // batchedOperationID, + // EMPTY_SALT + // ); + // } + + // function testBatchPredecessorNotScheduled() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // vm.startPrank(PROPOSER_ONE); + + // // Prepare predecessor job + // bytes32 operationOneID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // bytes32 operationOneID2 = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // operationOneID, + // EMPTY_SALT + // ); + + // // Schedule dependent job + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // operationOneID2, + // i, + // targets[i], + // values[i], + // payloads[i], + // operationOneID, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // operationOneID, + // EMPTY_SALT, + // MIN_DELAY + // ); + // vm.stopPrank(); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // operationOneID, + // EMPTY_SALT + // ); + // } + + // function testBatchPredecessorInvalid() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // // Prepare invalid predecessor + // bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // invalidPredecessor, + // EMPTY_SALT + // ); + + // // Schedule dependent job + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // invalidPredecessor, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // invalidPredecessor, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // invalidPredecessor, + // EMPTY_SALT + // ); + // } + + // function testBatchTargetRevert() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // // Schedule a job where one target will revert + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + // vm.expectRevert("Transaction reverted"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testBatchPredecessorMultipleNotExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // // Schedule predecessor job + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); + + // // Schedule dependent job + // vm.prank(PROPOSER_ONE); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // batchedOperationID, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // // Check that executing the dependent job reverts + // vm.warp(block.timestamp + MIN_DELAY + 2 days); + // vm.expectRevert("TimelockController: missing dependency"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // batchedOperationID, + // EMPTY_SALT + // ); + // } + + // function testBatchCancelFinished() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY + 1); + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // vm.prank(PROPOSER_ONE); + // vm.expectRevert("TimelockController: operation cannot be cancelled"); + // timelockController.cancel(batchedOperationID); + // } + + // function testBatchPendingIfNotYetExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // bool is_operation_pending = timelockController.is_operation_pending( + // batchedOperationID + // ); + // assertEq(is_operation_pending, true); + // } + + // function testBatchPendingIfExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // bool is_operation_pending = timelockController.is_operation_pending( + // batchedOperationID + // ); + // assertEq(is_operation_pending, false); + // } + + // function testBatchReadyOnTheExecutionTime() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // bool is_operation_ready = timelockController.is_operation_ready( + // batchedOperationID + // ); + // assertEq(is_operation_ready, true); + // } + + // function testBatchReadyAfterTheExecutionTime() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY + 1 days); + + // bool is_operation_ready = timelockController.is_operation_ready( + // batchedOperationID + // ); + // assertEq(is_operation_ready, true); + // } + + // function testBatchReadyBeforeTheExecutionTime() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY - 1 days); + + // bool is_operation_ready = timelockController.is_operation_ready( + // batchedOperationID + // ); + // assertEq(is_operation_ready, false); + // } + + // function testBatchHasBeenExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // bool is_operation_ready = timelockController.is_operation_ready( + // batchedOperationID + // ); + // assertEq(is_operation_ready, false); + + // bool is_operation_done = timelockController.is_operation_done( + // batchedOperationID + // ); + // assertEq(is_operation_done, true); + // } + + // function testBatchHasNotBeenExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // bool is_operation_done = timelockController.is_operation_done( + // batchedOperationID + // ); + // assertEq(is_operation_done, false); + // } + + // function testBatchTimestampHasNotBeenExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, block.timestamp + MIN_DELAY); + // } + + // function testBatchTimestampHasBeenExecuted() public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // } + + // function testFuzzBatchValue(uint256 amount) public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory values = new uint256[](1); + // values[0] = amount; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // deal(address(timelockController), amount); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(address(counter).balance, values[0]); + // } + + // function testBatchERC1155() public { + // ERC1155Mock erc1155 = new ERC1155Mock(""); + // erc1155.mint(address(timelockController), 1, 1, bytes("")); + + // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc1155); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector( + // ERC1155Mock.burn.selector, + // address(timelockController), + // 1, + // 1 + // ); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); + // } + + // function testBatchERC721() public { + // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); + // erc721.mint(address(timelockController), 1); + + // assertEq(erc721.balanceOf(address(timelockController)), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc721); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); + + // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallScheduled( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(); + // emit ITimelockController.CallExecuted( + // batchedOperationID, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationID + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc721.balanceOf(address(timelockController)), 0); + // } + + // /*////////////////////////////////////////////////////////////// + // SANITY CHECKS TESTS + // //////////////////////////////////////////////////////////////*/ + + // function testReturnsLaterMinDelayForCalls() public { + // uint256 newMinDelay = 31 days; + // _laterDelay(newMinDelay); + // uint256 minDelay = timelockController.get_minimum_delay(); + // assertEq(minDelay, newMinDelay); + // } + + // function testInvalidOperation() public { + // bool is_operation = timelockController.is_operation(bytes32("non-op")); + // assertEq(is_operation, false); + // } + + // // Hash calculation + // function testHashOperationBatch() public { + // address[] memory targets = new address[](2); + // targets[0] = address(this); + // targets[1] = address(this); + + // uint256[] memory values = new uint256[](2); + // values[0] = 0; + // values[1] = 1; + + // bytes[] memory payloads = new bytes[](2); + // payloads[0] = abi.encodeWithSelector( + // this.testHashOperationBatch.selector + // ); + // payloads[1] = abi.encodeWithSelector( + // this.testHashOperationBatch.selector + // ); + + // bytes32 hashedOperation = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // bytes32 expectedHash = keccak256( + // abi.encode(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT) + // ); + // assertEq(hashedOperation, expectedHash); + // } + + // function testHashOperation() public { + // address target = address(this); + // uint256 amount = 1; + // bytes memory payload = abi.encodeWithSelector( + // this.testHashOperationBatch.selector + // ); + + // bytes32 hashedOperation = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // bytes32 expectedHash = keccak256( + // abi.encode(target, amount, payload, NO_PREDECESSOR, EMPTY_SALT) + // ); + // assertEq(hashedOperation, expectedHash); + // } + + // // TODO: Add NFTs tests + + // /*////////////////////////////////////////////////////////////// + // PERMISSION TESTS + // //////////////////////////////////////////////////////////////*/ + + // // Timelock + + // function testRevertWhenNotTimelock() public { + // vm.expectRevert("TimelockController: caller must be timelock"); + // vm.prank(STRANGER); + // timelockController.update_delay(3 days); + // } + + // // Admin + + // function testAdminCantBatchSchedule() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(ADMIN); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + // } + + // function testAdminCantSchedule() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(ADMIN); + // timelockController.schedule( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + // } + + // function testAdminCantBatchExecute() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(ADMIN); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testAdminCantExecute() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(ADMIN); + // timelockController.execute( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testAdminCantCancel() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(ADMIN); + // timelockController.cancel(EMPTY_SALT); + // } + + // // Proposer + + // function testProposerCanBatchSchedule() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.prank(PROPOSER_ONE); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.prank(PROPOSER_TWO); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // bytes32("1"), + // MIN_DELAY + // ); + // } + + // function testProposerCanSchedule() public { + // vm.prank(PROPOSER_ONE); + // timelockController.schedule( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.prank(PROPOSER_TWO); + // timelockController.schedule( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // bytes32("1"), + // MIN_DELAY + // ); + // } + + // function testProposerCantBatchExecute() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(PROPOSER_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(PROPOSER_TWO); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // bytes32("1") + // ); + // } + + // function testProposerCantExecute() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(PROPOSER_ONE); + // timelockController.execute( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(PROPOSER_TWO); + // timelockController.execute( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // bytes32("1") + // ); + // } + + // function testProposerCanCancel() public { + // vm.expectRevert("TimelockController: operation cannot be cancelled"); + // vm.prank(PROPOSER_ONE); + // timelockController.cancel(EMPTY_SALT); + + // vm.expectRevert("TimelockController: operation cannot be cancelled"); + // vm.prank(PROPOSER_TWO); + // timelockController.cancel(EMPTY_SALT); + // } + + // // Executor + + // function testExecutorCantBatchSchedule() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(EXECUTOR_ONE); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(EXECUTOR_TWO); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // bytes32("1"), + // MIN_DELAY + // ); + // } + + // function testExecutorCantSchedule() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(EXECUTOR_ONE); + // timelockController.schedule( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(EXECUTOR_TWO); + // timelockController.schedule( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // bytes32("1"), + // MIN_DELAY + // ); + // } + + // function testExecutorCanBatchExecute() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.expectRevert("TimelockController: operation is not ready"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.expectRevert("TimelockController: operation is not ready"); + // vm.prank(EXECUTOR_TWO); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // bytes32("1") + // ); + // } + + // function testExecutorCanExecute() public { + // vm.expectRevert("TimelockController: operation is not ready"); + // vm.prank(EXECUTOR_ONE); + // timelockController.execute( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.expectRevert("TimelockController: operation is not ready"); + // vm.prank(EXECUTOR_TWO); + // timelockController.execute( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // bytes32("1") + // ); + // } + + // function testExecutorCantCancel() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(EXECUTOR_ONE); + // timelockController.cancel(EMPTY_SALT); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(EXECUTOR_TWO); + // timelockController.cancel(EMPTY_SALT); + // } + + // // Stanger + + // function testStrangerCantBatchSchedule() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(STRANGER); + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + // } + + // function testStrangerCantSchedule() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(STRANGER); + // timelockController.schedule( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + // } + + // function testStrangerCantBatchExecute() public { + // address[] memory targets = new address[](0); + // uint256[] memory values = new uint256[](0); + // bytes[] memory payloads = new bytes[](0); + + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(STRANGER); + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testStrangerCantExecute() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(STRANGER); + // timelockController.execute( + // address(0), + // 0, + // bytes(""), + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + // } + + // function testStrangerCantCancel() public { + // vm.expectRevert("AccessControl: account is missing role"); + // vm.prank(STRANGER); + // timelockController.cancel(EMPTY_SALT); + // } + + // // TODO: Move this somewhere in correct place + // function testCancellerCanCancelOperation() public { + // bytes32 operationID = _cancelOperation(); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(); + // emit ITimelockController.Cancelled(operationID); + // timelockController.cancel(operationID); + // assertTrue(!timelockController.is_operation(operationID)); + // } } -contract TimelockControllerHandler is Test { - ITimelockController private timelockController; - uint256 private minDelay; - address private admin; - address private proposer; - address private executor; - - uint256 public counter; - - uint256 public schedule_count; - uint256 public execute_count; - uint256 public cancel_count; - - uint256[] public pending; - uint256[] public executed; - uint256[] public cancelled; - - constructor( - ITimelockController timelockController_, - uint256 minDelay_, - address[] memory proposer_, - address[] memory executor_, - address admin_ - ) { - timelockController = timelockController_; - minDelay = minDelay_; - proposer = proposer_[0]; - executor = executor_[0]; - admin = admin_; - } - - function schedule(uint256 random) external { - vm.prank(proposer); - timelockController.schedule( - address(this), - 0, - abi.encodeWithSelector(this.increment.selector), - bytes32(""), - bytes32(random), - minDelay - ); - - pending.push(random); - schedule_count++; - } - - function execute(uint256 random) external { - if (pending.length == 0 || schedule_count == 0) { - return; - } - - uint256 identifier = random % pending.length; - uint256 operation = pending[identifier]; - - // Advance time to make the proposal ready. - vm.warp(block.timestamp + minDelay); - - vm.prank(executor); - timelockController.execute( - address(this), - 0, - abi.encodeWithSelector(this.increment.selector), - bytes32(""), - bytes32(operation) - ); - - delete pending[identifier]; - executed.push(operation); - - execute_count++; - } - - function cancel(uint256 random) external { - if (pending.length == 0 || schedule_count == 0) { - return; - } - - uint256 identifier = random % pending.length; - uint256 operation = pending[identifier]; - - vm.prank(proposer); - timelockController.cancel(bytes32(operation)); - - delete pending[identifier]; - cancelled.push(operation); - - cancel_count++; - } - - function getExecuted() external view returns (uint256[] memory) { - return executed; - } - - function getCancelled() external view returns (uint256[] memory) { - return cancelled; - } - - function getPending() external view returns (uint256[] memory) { - return pending; - } - - function increment() external { - counter++; - } -} +// contract TimelockControllerInvariants is Test { +// VyperDeployer private vyperDeployer = new VyperDeployer(); + +// ITimelockController private timelockController; +// TimelockControllerHandler private timelockControllerHandler; + +// function setUp() public { +// address[] memory proposers = new address[](1); +// proposers[0] = address(this); + +// address[] memory executors = new address[](1); +// executors[0] = address(this); + +// uint256 minDelay = 2 days; + +// bytes memory args = abi.encode( +// minDelay, +// proposers, +// executors, +// address(this) +// ); +// timelockController = ITimelockController( +// payable( +// vyperDeployer.deployContract( +// "src/governance/", +// "TimelockController", +// args +// ) +// ) +// ); + +// timelockControllerHandler = new TimelockControllerHandler( +// timelockController, +// minDelay, +// proposers, +// executors, +// address(this) +// ); + +// // Select the selectors to use for fuzzing. +// bytes4[] memory selectors = new bytes4[](3); +// selectors[0] = TimelockControllerHandler.schedule.selector; +// selectors[1] = TimelockControllerHandler.execute.selector; +// selectors[2] = TimelockControllerHandler.cancel.selector; + +// // Set the target selector. +// targetSelector( +// FuzzSelector({ +// addr: address(timelockControllerHandler), +// selectors: selectors +// }) +// ); + +// // Set the target contract. +// targetContract(address(timelockControllerHandler)); +// } + +// // Number of pending transactions cannot exceed executed transactions +// function invariantExecutedLessThanOrEqualToPending() public { +// assertLe( +// timelockControllerHandler.execute_count(), +// timelockControllerHandler.schedule_count() +// ); +// } + +// // Number of proposals executed must match the count number. +// function invariantProposalsExecutedMatchCount() public { +// assertEq( +// timelockControllerHandler.execute_count(), +// timelockControllerHandler.counter() +// ); +// } + +// // Proposals can only be scheduled and executed once +// function invariantOnceProposalExecution() public { +// uint256[] memory executed = timelockControllerHandler.getExecuted(); +// // Loop over all executed proposals. +// for (uint256 i = 0; i < executed.length; ++i) { +// // Check that the executed proposal cannot be executed again. +// vm.expectRevert("TimelockController: operation is not ready"); +// timelockController.execute( +// address(timelockControllerHandler), +// 0, +// abi.encodeWithSelector( +// TimelockControllerHandler.increment.selector +// ), +// bytes32(""), +// bytes32(executed[i]) +// ); +// } +// } + +// // Sum of number of executed proposals and cancelled proposals must be less or equal to the amount of proposals scheduled. +// function invariantSumOfProposals() public { +// assertLe( +// timelockControllerHandler.cancel_count() + +// timelockControllerHandler.execute_count(), +// timelockControllerHandler.schedule_count() +// ); +// } + +// // Executed proposals cannot be cancelled +// function invariantExecutedProposalCancellation() public { +// uint256[] memory executed = timelockControllerHandler.getExecuted(); +// // Loop over all executed proposals. +// for (uint256 i = 0; i < executed.length; ++i) { +// // Check that the executed proposal cannot be cancelled. +// vm.expectRevert( +// "TimelockController: operation cannot be cancelled" +// ); +// timelockController.cancel(bytes32(executed[i])); +// } +// } + +// // Executing a proposal that has been cancelled is not possible +// function invariantExecutingCancelledProposal() public { +// uint256[] memory cancelled = timelockControllerHandler.getCancelled(); +// // Loop over all cancelled proposals. +// for (uint256 i = 0; i < cancelled.length; ++i) { +// // Check that the cancelled proposal cannot be executed. +// vm.expectRevert("TimelockController: operation is not ready"); +// timelockController.execute( +// address(timelockControllerHandler), +// 0, +// abi.encodeWithSelector( +// TimelockControllerHandler.increment.selector +// ), +// bytes32(""), +// bytes32(cancelled[i]) +// ); +// } +// } + +// // Executing a proposal that is not ready is not possible +// function invariantExecutingNotReadyProposal() public { +// uint256[] memory pending = timelockControllerHandler.getPending(); +// // Loop over all pending proposals. +// for (uint256 i = 0; i < pending.length; ++i) { +// // Check that the pending proposal cannot be executed. +// vm.expectRevert("TimelockController: operation is not ready"); +// timelockController.execute( +// address(timelockControllerHandler), +// 0, +// abi.encodeWithSelector( +// TimelockControllerHandler.increment.selector +// ), +// bytes32(""), +// bytes32(pending[i]) +// ); +// } +// } +// } + +// contract TimelockControllerHandler is Test { +// ITimelockController private timelockController; +// uint256 private minDelay; +// address private admin; +// address private proposer; +// address private executor; + +// uint256 public counter; + +// uint256 public schedule_count; +// uint256 public execute_count; +// uint256 public cancel_count; + +// uint256[] public pending; +// uint256[] public executed; +// uint256[] public cancelled; + +// constructor( +// ITimelockController timelockController_, +// uint256 minDelay_, +// address[] memory proposer_, +// address[] memory executor_, +// address admin_ +// ) { +// timelockController = timelockController_; +// minDelay = minDelay_; +// proposer = proposer_[0]; +// executor = executor_[0]; +// admin = admin_; +// } + +// function schedule(uint256 random) external { +// vm.prank(proposer); +// timelockController.schedule( +// address(this), +// 0, +// abi.encodeWithSelector(this.increment.selector), +// bytes32(""), +// bytes32(random), +// minDelay +// ); + +// pending.push(random); +// schedule_count++; +// } + +// function execute(uint256 random) external { +// if (pending.length == 0 || schedule_count == 0) { +// return; +// } + +// uint256 identifier = random % pending.length; +// uint256 operation = pending[identifier]; + +// // Advance time to make the proposal ready. +// vm.warp(block.timestamp + minDelay); + +// vm.prank(executor); +// timelockController.execute( +// address(this), +// 0, +// abi.encodeWithSelector(this.increment.selector), +// bytes32(""), +// bytes32(operation) +// ); + +// delete pending[identifier]; +// executed.push(operation); + +// execute_count++; +// } + +// function cancel(uint256 random) external { +// if (pending.length == 0 || schedule_count == 0) { +// return; +// } + +// uint256 identifier = random % pending.length; +// uint256 operation = pending[identifier]; + +// vm.prank(proposer); +// timelockController.cancel(bytes32(operation)); + +// delete pending[identifier]; +// cancelled.push(operation); + +// cancel_count++; +// } + +// function getExecuted() external view returns (uint256[] memory) { +// return executed; +// } + +// function getCancelled() external view returns (uint256[] memory) { +// return cancelled; +// } + +// function getPending() external view returns (uint256[] memory) { +// return pending; +// } + +// function increment() external { +// counter++; +// } +// } diff --git a/test/governance/mocks/CallReceiverMock.sol b/test/governance/mocks/CallReceiverMock.sol new file mode 100644 index 00000000..d824bcbf --- /dev/null +++ b/test/governance/mocks/CallReceiverMock.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +/** + * @title CallReceiverMock + * @author pcaversaccio + * @custom:coauthor cairoeth + * @notice Forked and adjusted accordingly from here: + * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/CallReceiverMock.sol. + * @dev Allows to test receiving state-changing and/or static external calls. + */ +contract CallReceiverMock { + event MockFunctionCalled(); + event MockFunctionCalledWithArgs(uint256 a, uint256 b); + + string private _retValue = "0xba5ed"; + + /** + * @dev Emits `MockFunctionCalled` and returns the string `0xba5ed` + * after function invocation. + * @return string The return string `0xba5ed`. + */ + function mockFunction() public payable returns (string memory) { + emit MockFunctionCalled(); + return _retValue; + } + + /** + * @dev Emits `MockFunctionCalled` after function invocation. + */ + function mockFunctionEmptyReturn() public payable { + emit MockFunctionCalled(); + } + + /** + * @dev Emits `MockFunctionCalledWithArgs` and returns the string `0xba5ed` + * after function invocation. + * @param a The first 32-byte function argument. + * @param b The second 32-byte function argument. + * @return string The return string `0xba5ed`. + */ + function mockFunctionWithArgs( + uint256 a, + uint256 b + ) public payable returns (string memory) { + emit MockFunctionCalledWithArgs(a, b); + return _retValue; + } + + /** + * @dev Emits `MockFunctionCalled` and returns the string `0xba5ed` + * after function invocation. + * @notice `payable` function calls will revert. + * @return string The return string `0xba5ed`. + */ + function mockFunctionNonPayable() public returns (string memory) { + emit MockFunctionCalled(); + return _retValue; + } + + /** + * @dev Returns the string `0xba5ed` after function invocation. + * @notice Special function to mock `STATICCALL` calls. + * @return string The return string `0xba5ed`. + */ + function mockStaticFunction() public view returns (string memory) { + return _retValue; + } + + /** + * @dev Reverts with an empty reason. + */ + function mockFunctionRevertsWithEmptyReason() public payable { + // solhint-disable-next-line reason-string, custom-errors + revert(); + } + + /** + * @dev Reverts with a non-empty reason. + */ + function mockFunctionRevertsWithReason() public payable { + // solhint-disable-next-line custom-errors + revert("CallReceiverMock: reverting"); + } + + /** + * @dev Returns the string `0xba5ed` after function invocation. + * @param slot The 32-byte key in storage. + * @param value The 32-byte value to store at `slot`. + * @notice Writes to storage slot `slot` with value `value`. + * @return string The return string `0xba5ed`. + */ + function mockFunctionWritesStorage( + bytes32 slot, + bytes32 value + ) public returns (string memory) { + // solhint-disable-next-line no-inline-assembly + assembly { + sstore(slot, value) + } + return _retValue; + } +} diff --git a/test/tokens/mocks/ERC721ReceiverMock.sol b/test/tokens/mocks/ERC721ReceiverMock.sol index 03b46c89..6e327c20 100644 --- a/test/tokens/mocks/ERC721ReceiverMock.sol +++ b/test/tokens/mocks/ERC721ReceiverMock.sol @@ -11,16 +11,14 @@ import {IERC721Receiver} from "openzeppelin/token/ERC721/IERC721Receiver.sol"; * @dev Allows to test receiving ERC-721 tokens as a smart contract. */ contract ERC721ReceiverMock is IERC721Receiver { - // solhint-disable-next-line var-name-mixedcase - bytes4 private immutable _RETVAL; - enum Error { None, RevertWithMessage, RevertWithoutMessage, Panic } - // solhint-disable-next-line var-name-mixedcase + + bytes4 private immutable _RETVAL; Error private immutable _ERROR; event Received(address operator, address from, uint256 tokenId, bytes data); From 4c0401af16f102612a947d692c570097a321090b Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Tue, 30 Jan 2024 18:08:45 +0100 Subject: [PATCH 39/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/governance/TimelockController.t.sol | 2554 +++++++++++----------- 1 file changed, 1295 insertions(+), 1259 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index e558f58a..d0f0efe4 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -54,6 +54,7 @@ contract TimelockControllerTest is Test { address private deployer = address(vyperDeployer); address private self = address(this); + address private zeroAddress = address(0); address private target = address(callReceiverMock); address private timelockControllerAddr; address private timelockControllerInitialEventEmptyAdminAddr; @@ -451,7 +452,6 @@ contract TimelockControllerTest is Test { timelockControllerInitialEventNonEmptyAdminAddr = address( timelockControllerInitialEventNonEmptyAdmin ); - assertEq( timelockControllerInitialEventNonEmptyAdmin.DEFAULT_ADMIN_ROLE(), DEFAULT_ADMIN_ROLE @@ -645,6 +645,30 @@ contract TimelockControllerTest is Test { ); } + function testHashOperation() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq( + operationId, + keccak256( + abi.encode(target, amount, payload, NO_PREDECESSOR, EMPTY_SALT) + ) + ); + } + function testScheduleAndExecuteWithEmptySalt() public { uint256 amount = 0; bytes32 slot = bytes32(uint256(1337)); @@ -662,6 +686,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); assertEq(vm.load(target, slot), bytes32(uint256(0))); + assertEq(timelockController.is_operation(operationId), false); assertEq(timelockController.get_timestamp(operationId), 0); vm.startPrank(PROPOSER_ONE); @@ -683,6 +708,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); + assertEq(timelockController.is_operation(operationId), true); // solhint-disable-next-line not-rely-on-time assertEq( timelockController.get_timestamp(operationId), @@ -709,6 +735,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); assertEq(vm.load(target, slot), value); + assertEq(timelockController.is_operation(operationId), true); assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); vm.stopPrank(); } @@ -730,6 +757,7 @@ contract TimelockControllerTest is Test { SALT ); assertEq(vm.load(target, slot), bytes32(uint256(0))); + assertEq(timelockController.is_operation(operationId), false); assertEq(timelockController.get_timestamp(operationId), 0); vm.startPrank(PROPOSER_ONE); @@ -753,6 +781,7 @@ contract TimelockControllerTest is Test { SALT, MIN_DELAY ); + assertEq(timelockController.is_operation(operationId), true); // solhint-disable-next-line not-rely-on-time assertEq( timelockController.get_timestamp(operationId), @@ -779,6 +808,7 @@ contract TimelockControllerTest is Test { SALT ); assertEq(vm.load(target, slot), value); + assertEq(timelockController.is_operation(operationId), true); assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); vm.stopPrank(); } @@ -794,7 +824,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); vm.startPrank(PROPOSER_ONE); - vm.expectEmit(); + vm.expectEmit(true, true, false, true); emit ITimelockController.CallScheduled( operationId, 0, @@ -837,1173 +867,966 @@ contract TimelockControllerTest is Test { ); } - // function testOperationEqualAndGreaterMinDelay() public { - // address target = address(0); - // uint256 amount = 0; - // bytes memory payload = bytes(""); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // assertEq(timelockController.is_operation(operationID), true); - - // operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // bytes32("1") - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY + 1 - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // bytes32("1"), - // MIN_DELAY + 1 - // ); + function testOperationEqualAndGreaterMinimumDelay() public { + uint256 amount = 0; + bytes memory payload = new bytes(0); + bytes32 operationId = timelockController.hash_operation( + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // assertEq(timelockController.is_operation(operationID), true); - // } + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertEq(timelockController.is_operation(operationId), true); + vm.stopPrank(); - // function testOperationMinDelayUpdate() public { - // address target = address(0); - // uint256 amount = 0; - // bytes memory payload = bytes(""); + operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + SALT + ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + 1 + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + SALT, + MIN_DELAY + 1 + ); + assertEq(timelockController.is_operation(operationId), true); + vm.stopPrank(); + } - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testOperationMinimumDelayUpdate() public { + uint256 amount = 0; + bytes memory payload = new bytes(0); + bytes32 operationId = timelockController.hash_operation( + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + uint256 operationTimestampBefore = timelockController.get_timestamp( + operationId + ); + vm.stopPrank(); - // uint256 operationTimestampBefore = timelockController.get_timestamp( - // operationID - // ); + vm.startPrank(timelockControllerAddr); + vm.expectEmit(true, true, false, false); + emit ITimelockController.MinimumDelayChange( + MIN_DELAY, + MIN_DELAY + 31 days + ); + timelockController.update_delay(MIN_DELAY + 31 days); + uint256 operationTimestampAfter = timelockController.get_timestamp( + operationId + ); + assertEq(timelockController.get_minimum_delay(), MIN_DELAY + 31 days); + assertEq(operationTimestampAfter, operationTimestampBefore); + vm.stopPrank(); + } - // // Set a new delay value - // vm.prank(address(timelockController)); - // timelockController.update_delay(MIN_DELAY + 31 days); + function testOperationOperationIsNotReady() public { + uint256 amount = 0; + bytes memory payload = new bytes(0); + bytes32 operationId = timelockController.hash_operation( + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // // New delay value should only apply on future operations, not existing ones - // uint256 operationTimestampAfter = timelockController.get_timestamp( - // operationID - // ); - // assertEq(operationTimestampAfter, operationTimestampBefore); - // } + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // function testOperationOperationIsNotReady() public { - // address target = address(0); - // uint256 amount = 0; - // bytes memory payload = bytes(""); + vm.warp(block.timestamp + MIN_DELAY - 2 days); + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.execute( + zeroAddress, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + } - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testOperationPredecessorNotExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId1 = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + bytes32 operationId2 = timelockController.hash_operation( + target, + amount, + payload, + operationId1, + SALT + ); - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId1, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId2, + 0, + target, + amount, + payload, + operationId1, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + operationId1, + SALT, + MIN_DELAY + ); + vm.stopPrank(); - // vm.warp(block.timestamp + MIN_DELAY - 2 days); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute(target, amount, payload, operationId1, SALT); + } - // vm.expectRevert("TimelockController: operation is not ready"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } + function testOperationPredecessorNotScheduled() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId1 = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + bytes32 operationId2 = timelockController.hash_operation( + target, + amount, + payload, + operationId1, + SALT + ); - // function testOperationPredecessorNotExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId2, + 0, + target, + amount, + payload, + operationId1, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + operationId1, + SALT, + MIN_DELAY + ); + vm.stopPrank(); - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute(target, amount, payload, operationId1, SALT); + } - // vm.startPrank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + function testOperationPredecessorInvalid() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 invalidPredecessor = keccak256("Invalid Predecessor"); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + invalidPredecessor, + EMPTY_SALT + ); - // bytes32 operationID2 = timelockController.hash_operation( - // target, - // amount, - // payload, - // operationID, - // EMPTY_SALT - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + invalidPredecessor, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + invalidPredecessor, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // // Schedule dependent job - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID2, - // 0, - // target, - // amount, - // payload, - // operationID, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // operationID, - // EMPTY_SALT, - // MIN_DELAY - // ); - // vm.stopPrank(); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute( + target, + amount, + payload, + invalidPredecessor, + EMPTY_SALT + ); + } - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); + function testOperationTargetRevert() public { + uint256 amount = 0; + bytes memory payload1 = abi.encodeWithSelector( + callReceiverMock.mockFunctionRevertsWithReason.selector + ); + bytes memory payload2 = abi.encodeWithSelector( + callReceiverMock.mockFunctionRevertsWithEmptyReason.selector + ); + bytes32 operationId1 = timelockController.hash_operation( + target, + amount, + payload1, + NO_PREDECESSOR, + EMPTY_SALT + ); + bytes32 operationId2 = timelockController.hash_operation( + target, + amount, + payload2, + NO_PREDECESSOR, + SALT + ); - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute( - // target, - // amount, - // payload, - // operationID, - // EMPTY_SALT - // ); - // } + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId1, + 0, + target, + amount, + payload1, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload1, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId2, + 0, + target, + amount, + payload2, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload2, + NO_PREDECESSOR, + SALT, + MIN_DELAY + ); + vm.stopPrank(); - // function testOperationPredecessorNotScheduled() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("CallReceiverMock: reverting"); + vm.startPrank(EXECUTOR_ONE); + timelockController.execute( + target, + amount, + payload1, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.expectRevert("TimelockController: underlying transaction reverted"); + timelockController.execute( + target, + amount, + payload2, + NO_PREDECESSOR, + SALT + ); + vm.stopPrank(); + } - // bytes32 operationID1 = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // bytes32 operationID2 = timelockController.hash_operation( - // target, - // amount, - // payload, - // operationID1, - // EMPTY_SALT - // ); - - // // Schedule dependent job - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID2, - // 0, - // target, - // amount, - // payload, - // operationID1, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // operationID1, - // EMPTY_SALT, - // MIN_DELAY - // ); - // vm.stopPrank(); + function testOperationPredecessorMultipleNotExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute( - // target, - // amount, - // payload, - // operationID1, - // EMPTY_SALT - // ); - // } + payload = abi.encodeWithSelector( + callReceiverMock.mockFunction.selector + ); + vm.startPrank(PROPOSER_TWO); + timelockController.schedule( + target, + amount, + payload, + operationId, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // function testOperationPredecessorInvalid() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute( + target, + amount, + payload, + operationId, + EMPTY_SALT + ); + } - // // Prepare invalid predecessor - // bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; + function testOperationCancelFinished() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // invalidPredecessor, - // EMPTY_SALT - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // // Schedule dependent job - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // invalidPredecessor, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // invalidPredecessor, - // EMPTY_SALT, - // MIN_DELAY - // ); + vm.warp(block.timestamp + MIN_DELAY + 1); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.stopPrank(); - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.prank(PROPOSER_ONE); + vm.expectRevert("TimelockController: operation cannot be cancelled"); + timelockController.cancel(operationId); + } - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute( - // target, - // amount, - // payload, - // invalidPredecessor, - // EMPTY_SALT - // ); - // } + function testOperationPendingIfNotYetExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // function testOperationTargetRevert() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.mockRevert.selector - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertTrue(timelockController.is_operation_pending(operationId)); + vm.stopPrank(); + } - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testOperationPendingIfExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // // Schedule a job where one target will revert - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY + 2 days); - - // vm.expectRevert("Transaction reverted"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } - - // function testOperationPredecessorMultipleNotExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // // Schedule predecessor job - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // payload = abi.encodeWithSelector(Counter.setNumber.selector, 1); - - // // Schedule dependent job - // vm.prank(PROPOSER_ONE); - // timelockController.schedule( - // target, - // amount, - // payload, - // operationID, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); - - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute( - // target, - // amount, - // payload, - // operationID, - // EMPTY_SALT - // ); - // } - - // function testOperationCancelFinished() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY + 1); - - // vm.prank(EXECUTOR_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallExecuted( - // operationID, - // 0, - // target, - // amount, - // payload - // ); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // vm.prank(PROPOSER_ONE); - // vm.expectRevert("TimelockController: operation cannot be cancelled"); - // timelockController.cancel(operationID); - // } - - // function testOperationPendingIfNotYetExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // bool is_operation_pending = timelockController.is_operation_pending( - // operationID - // ); - // assertEq(is_operation_pending, true); - // } - - // function testOperationPendingIfExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallExecuted( - // operationID, - // 0, - // target, - // amount, - // payload - // ); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // bool is_operation_pending = timelockController.is_operation_pending( - // operationID - // ); - // assertEq(is_operation_pending, false); - // } - - // function testOperationReadyOnTheExecutionTime() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // bool is_operation_ready = timelockController.is_operation_ready( - // operationID - // ); - // assertEq(is_operation_ready, true); - // } - - // function testOperationReadyAfterTheExecutionTime() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY + 1 days); - - // bool is_operation_ready = timelockController.is_operation_ready( - // operationID - // ); - // assertEq(is_operation_ready, true); - // } - - // function testOperationReadyBeforeTheExecutionTime() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY - 1 days); - - // bool is_operation_ready = timelockController.is_operation_ready( - // operationID - // ); - // assertEq(is_operation_ready, false); - // } - - // function testOperationHasBeenExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - // vm.prank(EXECUTOR_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallExecuted( - // operationID, - // 0, - // target, - // amount, - // payload - // ); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // bool is_operation_ready = timelockController.is_operation_ready( - // operationID - // ); - // assertEq(is_operation_ready, false); - - // bool is_operation_done = timelockController.is_operation_done( - // operationID - // ); - // assertEq(is_operation_done, true); - // } - - // function testOperationHasNotBeenExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // bool is_operation_done = timelockController.is_operation_done( - // operationID - // ); - // assertEq(is_operation_done, false); - // } - - // function testOperationTimestampHasNotBeenExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // operationID - // ); - // assertEq(operationTimestamp, block.timestamp + MIN_DELAY); - // } - - // function testOperationTimestampHasBeenExecuted() public { - // address target = address(counter); - // uint256 amount = 0; - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - // vm.prank(EXECUTOR_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallExecuted( - // operationID, - // 0, - // target, - // amount, - // payload - // ); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // operationID - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // } - - // function testFuzzOperationValue(uint256 amount) public { - // address target = address(counter); - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationID = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // deal(address(timelockController), amount); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // operationID, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // vm.expectEmit(); - // emit ITimelockController.CallExecuted( - // operationID, - // 0, - // target, - // amount, - // payload - // ); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // operationID - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(address(counter).balance, amount); - // } - - // function testOperationERC1155() public { - // ERC1155Mock erc1155 = new ERC1155Mock(""); - // erc1155.mint(address(timelockController), 1, 1, bytes("")); - - // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); - - // address[] memory targets = new address[](1); - // targets[0] = address(erc1155); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertTrue(!timelockController.is_operation_pending(operationId)); + vm.stopPrank(); + } - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector( - // ERC1155Mock.burn.selector, - // address(timelockController), - // 1, - // 1 - // ); + function testOperationReadyOnTheExecutionTime() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.warp(block.timestamp + MIN_DELAY); + assertTrue(timelockController.is_operation_ready(operationId)); + vm.stopPrank(); + } - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // batchedOperationID, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + function testOperationReadyAfterTheExecutionTime() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.warp(block.timestamp + MIN_DELAY + 1 days); + assertTrue(timelockController.is_operation_ready(operationId)); + vm.stopPrank(); + } - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); - // emit ITimelockController.CallExecuted( - // batchedOperationID, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testOperationReadyBeforeTheExecutionTime() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); - // } + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.warp(block.timestamp + MIN_DELAY - 1 days); + assertTrue(!timelockController.is_operation_ready(operationId)); + vm.stopPrank(); + } - // function testOperationERC721() public { - // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); - // erc721.mint(address(timelockController), 1); + function testOperationHasBeenExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // assertEq(erc721.balanceOf(address(timelockController)), 1); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // address[] memory targets = new address[](1); - // targets[0] = address(erc721); + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertTrue(!timelockController.is_operation_ready(operationId)); + assertTrue(timelockController.is_operation_done(operationId)); + vm.stopPrank(); + } - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + function testOperationHasNotBeenExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertTrue(!timelockController.is_operation_done(operationId)); + vm.stopPrank(); + } - // bytes32 batchedOperationID = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testOperationTimestampHasNotBeenExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); - // emit ITimelockController.CallScheduled( - // batchedOperationID, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertEq( + timelockController.get_timestamp(operationId), + block.timestamp + MIN_DELAY + ); + vm.stopPrank(); + } - // vm.warp(block.timestamp + MIN_DELAY); + function testOperationTimestampHasBeenExecuted() public { + uint256 amount = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); - // emit ITimelockController.CallExecuted( - // batchedOperationID, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc721.balanceOf(address(timelockController)), 0); - // } + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); + vm.stopPrank(); + } // /*////////////////////////////////////////////////////////////// // BATCH TESTS @@ -2019,7 +1842,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2031,9 +1854,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2055,9 +1878,9 @@ contract TimelockControllerTest is Test { // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2083,9 +1906,9 @@ contract TimelockControllerTest is Test { // values[0] = 0; // bytes[] memory payloads = new bytes[](1); - // payloads[0] = bytes(""); + // payloads[0] = new bytes(0); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2095,9 +1918,9 @@ contract TimelockControllerTest is Test { // vm.startPrank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2134,7 +1957,7 @@ contract TimelockControllerTest is Test { // values[0] = 0; // bytes[] memory payloads = new bytes[](1); - // payloads[0] = bytes(""); + // payloads[0] = new bytes(0); // vm.expectRevert("TimelockController: insufficient delay"); // vm.prank(PROPOSER_ONE); @@ -2148,7 +1971,7 @@ contract TimelockControllerTest is Test { // ); // } - // function testBatchEqualAndGreaterMinDelay() public { + // function testBatchEqualAndGreaterMinimumDelay() public { // address[] memory targets = new address[](1); // targets[0] = address(0); @@ -2156,9 +1979,9 @@ contract TimelockControllerTest is Test { // values[0] = 0; // bytes[] memory payloads = new bytes[](1); - // payloads[0] = bytes(""); + // payloads[0] = new bytes(0); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2168,9 +1991,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2188,9 +2011,9 @@ contract TimelockControllerTest is Test { // MIN_DELAY // ); - // assertEq(timelockController.is_operation(batchedOperationID), true); + // assertEq(timelockController.is_operation(batchedoperationId), true); - // batchedOperationID = timelockController.hash_operation_batch( + // batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2200,9 +2023,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2220,10 +2043,10 @@ contract TimelockControllerTest is Test { // MIN_DELAY + 1 // ); - // assertEq(timelockController.is_operation(batchedOperationID), true); + // assertEq(timelockController.is_operation(batchedoperationId), true); // } - // function testBatchMinDelayUpdate() public { + // function testBatchMinimumDelayUpdate() public { // address[] memory targets = new address[](1); // targets[0] = address(0); @@ -2231,9 +2054,9 @@ contract TimelockControllerTest is Test { // values[0] = 0; // bytes[] memory payloads = new bytes[](1); - // payloads[0] = bytes(""); + // payloads[0] = new bytes(0); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2243,9 +2066,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2264,7 +2087,7 @@ contract TimelockControllerTest is Test { // ); // uint256 operationTimestampBefore = timelockController.get_timestamp( - // batchedOperationID + // batchedoperationId // ); // // Set a new delay value @@ -2273,7 +2096,7 @@ contract TimelockControllerTest is Test { // // New delay value should only apply on future operations, not existing ones // uint256 operationTimestampAfter = timelockController.get_timestamp( - // batchedOperationID + // batchedoperationId // ); // assertEq(operationTimestampAfter, operationTimestampBefore); // } @@ -2286,9 +2109,9 @@ contract TimelockControllerTest is Test { // values[0] = 0; // bytes[] memory payloads = new bytes[](1); - // payloads[0] = bytes(""); + // payloads[0] = new bytes(0); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2298,9 +2121,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2341,7 +2164,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2351,9 +2174,9 @@ contract TimelockControllerTest is Test { // vm.startPrank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2371,24 +2194,24 @@ contract TimelockControllerTest is Test { // MIN_DELAY // ); - // bytes32 batchedOperationID2 = timelockController.hash_operation_batch( + // bytes32 batchedoperationId2 = timelockController.hash_operation_batch( // targets, // values, // payloads, - // batchedOperationID, + // batchedoperationId, // EMPTY_SALT // ); // // Schedule dependent job // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID2, + // batchedoperationId2, // i, // targets[i], // values[i], // payloads[i], - // batchedOperationID, + // batchedoperationId, // MIN_DELAY // ); // } @@ -2396,7 +2219,7 @@ contract TimelockControllerTest is Test { // targets, // values, // payloads, - // batchedOperationID, + // batchedoperationId, // EMPTY_SALT, // MIN_DELAY // ); @@ -2410,7 +2233,7 @@ contract TimelockControllerTest is Test { // targets, // values, // payloads, - // batchedOperationID, + // batchedoperationId, // EMPTY_SALT // ); // } @@ -2446,7 +2269,7 @@ contract TimelockControllerTest is Test { // // Schedule dependent job // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( // operationOneID2, // i, @@ -2493,7 +2316,7 @@ contract TimelockControllerTest is Test { // // Prepare invalid predecessor // bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2504,9 +2327,9 @@ contract TimelockControllerTest is Test { // // Schedule dependent job // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2547,7 +2370,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2558,9 +2381,9 @@ contract TimelockControllerTest is Test { // // Schedule a job where one target will revert // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2600,7 +2423,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2611,9 +2434,9 @@ contract TimelockControllerTest is Test { // // Schedule predecessor job // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2639,7 +2462,7 @@ contract TimelockControllerTest is Test { // targets, // values, // payloads, - // batchedOperationID, + // batchedoperationId, // EMPTY_SALT, // MIN_DELAY // ); @@ -2652,7 +2475,7 @@ contract TimelockControllerTest is Test { // targets, // values, // payloads, - // batchedOperationID, + // batchedoperationId, // EMPTY_SALT // ); // } @@ -2667,7 +2490,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2677,9 +2500,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2700,9 +2523,9 @@ contract TimelockControllerTest is Test { // vm.warp(block.timestamp + MIN_DELAY + 1); // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2718,7 +2541,7 @@ contract TimelockControllerTest is Test { // ); // vm.prank(PROPOSER_ONE); // vm.expectRevert("TimelockController: operation cannot be cancelled"); - // timelockController.cancel(batchedOperationID); + // timelockController.cancel(batchedoperationId); // } // function testBatchPendingIfNotYetExecuted() public { @@ -2731,7 +2554,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2741,9 +2564,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2762,7 +2585,7 @@ contract TimelockControllerTest is Test { // ); // bool is_operation_pending = timelockController.is_operation_pending( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_pending, true); // } @@ -2777,7 +2600,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2787,9 +2610,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2810,9 +2633,9 @@ contract TimelockControllerTest is Test { // vm.warp(block.timestamp + MIN_DELAY); // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2828,7 +2651,7 @@ contract TimelockControllerTest is Test { // ); // bool is_operation_pending = timelockController.is_operation_pending( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_pending, false); // } @@ -2843,7 +2666,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2853,9 +2676,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2876,7 +2699,7 @@ contract TimelockControllerTest is Test { // vm.warp(block.timestamp + MIN_DELAY); // bool is_operation_ready = timelockController.is_operation_ready( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_ready, true); // } @@ -2891,7 +2714,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2901,9 +2724,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2924,7 +2747,7 @@ contract TimelockControllerTest is Test { // vm.warp(block.timestamp + MIN_DELAY + 1 days); // bool is_operation_ready = timelockController.is_operation_ready( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_ready, true); // } @@ -2939,7 +2762,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2949,9 +2772,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -2972,7 +2795,7 @@ contract TimelockControllerTest is Test { // vm.warp(block.timestamp + MIN_DELAY - 1 days); // bool is_operation_ready = timelockController.is_operation_ready( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_ready, false); // } @@ -2987,7 +2810,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -2997,9 +2820,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3020,9 +2843,9 @@ contract TimelockControllerTest is Test { // vm.warp(block.timestamp + MIN_DELAY); // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3038,12 +2861,12 @@ contract TimelockControllerTest is Test { // ); // bool is_operation_ready = timelockController.is_operation_ready( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_ready, false); // bool is_operation_done = timelockController.is_operation_done( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_done, true); // } @@ -3058,7 +2881,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -3068,9 +2891,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3089,7 +2912,7 @@ contract TimelockControllerTest is Test { // ); // bool is_operation_done = timelockController.is_operation_done( - // batchedOperationID + // batchedoperationId // ); // assertEq(is_operation_done, false); // } @@ -3104,7 +2927,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -3114,9 +2937,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3135,7 +2958,7 @@ contract TimelockControllerTest is Test { // ); // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID + // batchedoperationId // ); // assertEq(operationTimestamp, block.timestamp + MIN_DELAY); // } @@ -3150,7 +2973,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -3160,9 +2983,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3183,9 +3006,9 @@ contract TimelockControllerTest is Test { // vm.warp(block.timestamp + MIN_DELAY); // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3201,7 +3024,7 @@ contract TimelockControllerTest is Test { // ); // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID + // batchedoperationId // ); // assertEq(operationTimestamp, DONE_TIMESTAMP); // } @@ -3218,7 +3041,7 @@ contract TimelockControllerTest is Test { // deal(address(timelockController), amount); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -3228,9 +3051,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3252,9 +3075,9 @@ contract TimelockControllerTest is Test { // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3270,7 +3093,7 @@ contract TimelockControllerTest is Test { // ); // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID + // batchedoperationId // ); // assertEq(operationTimestamp, DONE_TIMESTAMP); // assertEq(address(counter).balance, values[0]); @@ -3278,7 +3101,7 @@ contract TimelockControllerTest is Test { // function testBatchERC1155() public { // ERC1155Mock erc1155 = new ERC1155Mock(""); - // erc1155.mint(address(timelockController), 1, 1, bytes("")); + // erc1155.mint(address(timelockController), 1, 1, new bytes(0)); // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); @@ -3296,7 +3119,7 @@ contract TimelockControllerTest is Test { // 1 // ); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -3306,9 +3129,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3330,9 +3153,9 @@ contract TimelockControllerTest is Test { // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3348,7 +3171,7 @@ contract TimelockControllerTest is Test { // ); // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID + // batchedoperationId // ); // assertEq(operationTimestamp, DONE_TIMESTAMP); // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); @@ -3369,7 +3192,7 @@ contract TimelockControllerTest is Test { // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); - // bytes32 batchedOperationID = timelockController.hash_operation_batch( + // bytes32 batchedoperationId = timelockController.hash_operation_batch( // targets, // values, // payloads, @@ -3379,9 +3202,9 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3403,9 +3226,9 @@ contract TimelockControllerTest is Test { // vm.prank(EXECUTOR_ONE); // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(); + // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedOperationID, + // batchedoperationId, // i, // targets[i], // values[i], @@ -3421,7 +3244,7 @@ contract TimelockControllerTest is Test { // ); // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationID + // batchedoperationId // ); // assertEq(operationTimestamp, DONE_TIMESTAMP); // assertEq(erc721.balanceOf(address(timelockController)), 0); @@ -3431,7 +3254,7 @@ contract TimelockControllerTest is Test { // SANITY CHECKS TESTS // //////////////////////////////////////////////////////////////*/ - // function testReturnsLaterMinDelayForCalls() public { + // function testReturnsLaterMinimumDelayForCalls() public { // uint256 newMinDelay = 31 days; // _laterDelay(newMinDelay); // uint256 minDelay = timelockController.get_minimum_delay(); @@ -3533,7 +3356,7 @@ contract TimelockControllerTest is Test { // timelockController.schedule( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT, // MIN_DELAY @@ -3562,7 +3385,7 @@ contract TimelockControllerTest is Test { // timelockController.execute( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT // ); @@ -3607,7 +3430,7 @@ contract TimelockControllerTest is Test { // timelockController.schedule( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT, // MIN_DELAY @@ -3617,7 +3440,7 @@ contract TimelockControllerTest is Test { // timelockController.schedule( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // bytes32("1"), // MIN_DELAY @@ -3656,7 +3479,7 @@ contract TimelockControllerTest is Test { // timelockController.execute( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT // ); @@ -3666,7 +3489,7 @@ contract TimelockControllerTest is Test { // timelockController.execute( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // bytes32("1") // ); @@ -3718,7 +3541,7 @@ contract TimelockControllerTest is Test { // timelockController.schedule( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT, // MIN_DELAY @@ -3729,7 +3552,7 @@ contract TimelockControllerTest is Test { // timelockController.schedule( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // bytes32("1"), // MIN_DELAY @@ -3768,7 +3591,7 @@ contract TimelockControllerTest is Test { // timelockController.execute( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT // ); @@ -3778,7 +3601,7 @@ contract TimelockControllerTest is Test { // timelockController.execute( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // bytes32("1") // ); @@ -3819,7 +3642,7 @@ contract TimelockControllerTest is Test { // timelockController.schedule( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT, // MIN_DELAY @@ -3848,7 +3671,7 @@ contract TimelockControllerTest is Test { // timelockController.execute( // address(0), // 0, - // bytes(""), + // new bytes(0), // NO_PREDECESSOR, // EMPTY_SALT // ); @@ -3862,13 +3685,226 @@ contract TimelockControllerTest is Test { // // TODO: Move this somewhere in correct place // function testCancellerCanCancelOperation() public { - // bytes32 operationID = _cancelOperation(); + // bytes32 operationId = _cancelOperation(); + + // vm.prank(PROPOSER_ONE); + // vm.expectEmit(true, false, false, false); + // emit ITimelockController.Cancelled(operationId); + // timelockController.cancel(operationId); + // assertTrue(!timelockController.is_operation(operationId)); + // } + + // function testOperationERC721() public { + // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); + // erc721.mint(address(timelockController), 1); + + // assertEq(erc721.balanceOf(address(timelockController)), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc721); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); + + // bytes32 batchedoperationId = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallScheduled( + // batchedoperationId, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallExecuted( + // batchedoperationId, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedoperationId + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc721.balanceOf(address(timelockController)), 0); + // } + + // function testOperationERC1155() public { + // ERC1155Mock erc1155 = new ERC1155Mock(""); + // erc1155.mint(address(timelockController), 1, 1, new bytes(0)); + + // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc1155); + + // uint256[] memory values = new uint256[](1); + // values[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector( + // ERC1155Mock.burn.selector, + // address(timelockController), + // 1, + // 1 + // ); + + // bytes32 batchedoperationId = timelockController.hash_operation_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallScheduled( + // batchedoperationId, + // i, + // targets[i], + // values[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallExecuted( + // batchedoperationId, + // i, + // targets[i], + // values[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // values, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedoperationId + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); + // } + + // function testFuzzOperationValue(uint256 amount) public { + // address target = address(counter); + // bytes memory payload = abi.encodeWithSelector( + // Counter.increment.selector + // ); + + // bytes32 operationId = timelockController.hash_operation( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // deal(address(timelockController), amount); // vm.prank(PROPOSER_ONE); - // vm.expectEmit(); - // emit ITimelockController.Cancelled(operationID); - // timelockController.cancel(operationID); - // assertTrue(!timelockController.is_operation(operationID)); + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallScheduled( + // operationId, + // 0, + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // timelockController.schedule( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallExecuted( + // operationId, + // 0, + // target, + // amount, + // payload + // ); + // timelockController.execute( + // target, + // amount, + // payload, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // operationId + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(address(counter).balance, amount); // } } From 89b0bb2283151a3200a9a161a48d6793535f276a Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Tue, 30 Jan 2024 18:38:39 +0100 Subject: [PATCH 40/46] =?UTF-8?q?=F0=9F=92=84=20Remove=20obsolete=20solhin?= =?UTF-8?q?t=20rule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/extensions/ERC4626.t.sol | 8 -------- test/governance/TimelockController.t.sol | 4 ---- test/tokens/ERC20.t.sol | 8 -------- test/tokens/ERC721.t.sol | 8 -------- test/utils/EIP712DomainSeparator.t.sol | 2 -- 5 files changed, 30 deletions(-) diff --git a/test/extensions/ERC4626.t.sol b/test/extensions/ERC4626.t.sol index 7c526658..e1e8e3d1 100644 --- a/test/extensions/ERC4626.t.sol +++ b/test/extensions/ERC4626.t.sol @@ -1596,7 +1596,6 @@ contract ERC4626VaultTest is ERC4626Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 .DOMAIN_SEPARATOR(); @@ -1642,7 +1641,6 @@ contract ERC4626VaultTest is ERC4626Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 .DOMAIN_SEPARATOR(); @@ -1693,7 +1691,6 @@ contract ERC4626VaultTest is ERC4626Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 .DOMAIN_SEPARATOR(); @@ -1733,7 +1730,6 @@ contract ERC4626VaultTest is ERC4626Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = keccak256( abi.encode( @@ -1780,7 +1776,6 @@ contract ERC4626VaultTest is ERC4626Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = 1; - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 .DOMAIN_SEPARATOR(); @@ -1820,7 +1815,6 @@ contract ERC4626VaultTest is ERC4626Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp - 1; bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 .DOMAIN_SEPARATOR(); @@ -1915,7 +1909,6 @@ contract ERC4626VaultTest is ERC4626Test { address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 .DOMAIN_SEPARATOR(); @@ -1969,7 +1962,6 @@ contract ERC4626VaultTest is ERC4626Test { address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC4626ExtendedDecimalsOffset0.nonces(ownerAddr); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; bytes32 domainSeparator = ERC4626ExtendedDecimalsOffset0 .DOMAIN_SEPARATOR(); diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index d0f0efe4..d0254b30 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -709,14 +709,12 @@ contract TimelockControllerTest is Test { MIN_DELAY ); assertEq(timelockController.is_operation(operationId), true); - // solhint-disable-next-line not-rely-on-time assertEq( timelockController.get_timestamp(operationId), block.timestamp + MIN_DELAY ); vm.stopPrank(); - // solhint-disable-next-line not-rely-on-time vm.warp(block.timestamp + MIN_DELAY); vm.startPrank(EXECUTOR_ONE); vm.expectEmit(true, true, false, true); @@ -782,14 +780,12 @@ contract TimelockControllerTest is Test { MIN_DELAY ); assertEq(timelockController.is_operation(operationId), true); - // solhint-disable-next-line not-rely-on-time assertEq( timelockController.get_timestamp(operationId), block.timestamp + MIN_DELAY ); vm.stopPrank(); - // solhint-disable-next-line not-rely-on-time vm.warp(block.timestamp + MIN_DELAY); vm.startPrank(EXECUTOR_ONE); vm.expectEmit(true, true, false, true); diff --git a/test/tokens/ERC20.t.sol b/test/tokens/ERC20.t.sol index 56e02b2d..0c3f3a21 100644 --- a/test/tokens/ERC20.t.sol +++ b/test/tokens/ERC20.t.sol @@ -575,7 +575,6 @@ contract ERC20Test is Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC20Extended.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC20Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -609,7 +608,6 @@ contract ERC20Test is Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC20Extended.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC20Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -643,7 +641,6 @@ contract ERC20Test is Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC20Extended.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC20Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -674,7 +671,6 @@ contract ERC20Test is Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC20Extended.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = keccak256( abi.encode( @@ -713,7 +709,6 @@ contract ERC20Test is Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = 1; - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC20Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -744,7 +739,6 @@ contract ERC20Test is Test { address spender = makeAddr("spender"); uint256 amount = 100; uint256 nonce = ERC20Extended.nonces(owner); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp - 1; bytes32 domainSeparator = ERC20Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -1076,7 +1070,6 @@ contract ERC20Test is Test { address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC20Extended.nonces(ownerAddr); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; bytes32 domainSeparator = ERC20Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -1118,7 +1111,6 @@ contract ERC20Test is Test { address spenderAddr = makeAddr(spender); uint256 amount = block.number; uint256 nonce = ERC20Extended.nonces(ownerAddr); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; bytes32 domainSeparator = ERC20Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( diff --git a/test/tokens/ERC721.t.sol b/test/tokens/ERC721.t.sol index b1e69816..e47f9fa2 100644 --- a/test/tokens/ERC721.t.sol +++ b/test/tokens/ERC721.t.sol @@ -1629,7 +1629,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = ERC721Extended.nonces(tokenId); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC721Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -1667,7 +1666,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = ERC721Extended.nonces(tokenId); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC721Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -1705,7 +1703,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = ERC721Extended.nonces(tokenId); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC721Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -1740,7 +1737,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = ERC721Extended.nonces(tokenId); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = keccak256( abi.encode( @@ -1783,7 +1779,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = 1; - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 domainSeparator = ERC721Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -1818,7 +1813,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = 1; - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp - 1; bytes32 domainSeparator = ERC721Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -2353,7 +2347,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = ERC721Extended.nonces(tokenId); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; bytes32 domainSeparator = ERC721Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( @@ -2399,7 +2392,6 @@ contract ERC721Test is Test { vm.stopPrank(); uint256 nonce = ERC721Extended.nonces(tokenId); - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; bytes32 domainSeparator = ERC721Extended.DOMAIN_SEPARATOR(); (uint8 v, bytes32 r, bytes32 s) = vm.sign( diff --git a/test/utils/EIP712DomainSeparator.t.sol b/test/utils/EIP712DomainSeparator.t.sol index 08c98f48..b09f66ad 100644 --- a/test/utils/EIP712DomainSeparator.t.sol +++ b/test/utils/EIP712DomainSeparator.t.sol @@ -83,7 +83,6 @@ contract EIP712DomainSeparatorTest is Test { address spender = makeAddr("spender"); uint256 value = 100; uint256 nonce = 1; - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + 100_000; bytes32 structHash = keccak256( abi.encode( @@ -161,7 +160,6 @@ contract EIP712DomainSeparatorTest is Test { uint256 nonce, uint64 increment ) public { - // solhint-disable-next-line not-rely-on-time uint256 deadline = block.timestamp + increment; bytes32 structHash = keccak256( abi.encode( From b28e00a1fbd9f6d67639e9b59a541e9b9a43160f Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Wed, 31 Jan 2024 11:14:04 +0100 Subject: [PATCH 41/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/governance/TimelockController.t.sol | 3111 +++++++++-------- .../interfaces/ITimelockController.sol | 16 +- 2 files changed, 1637 insertions(+), 1490 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index d0254b30..227a70b5 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -686,7 +686,8 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); assertEq(vm.load(target, slot), bytes32(uint256(0))); - assertEq(timelockController.is_operation(operationId), false); + assertTrue(!timelockController.is_operation(operationId)); + assertEq(timelockController.get_operation_state(operationId), 1); assertEq(timelockController.get_timestamp(operationId), 0); vm.startPrank(PROPOSER_ONE); @@ -708,14 +709,16 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - assertEq(timelockController.is_operation(operationId), true); + assertTrue(timelockController.is_operation(operationId)); assertEq( timelockController.get_timestamp(operationId), block.timestamp + MIN_DELAY ); vm.stopPrank(); + assertEq(timelockController.get_operation_state(operationId), 2); vm.warp(block.timestamp + MIN_DELAY); + assertEq(timelockController.get_operation_state(operationId), 4); vm.startPrank(EXECUTOR_ONE); vm.expectEmit(true, true, false, true); emit ITimelockController.CallExecuted( @@ -733,8 +736,9 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); assertEq(vm.load(target, slot), value); - assertEq(timelockController.is_operation(operationId), true); + assertTrue(timelockController.is_operation(operationId)); assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); + assertEq(timelockController.get_operation_state(operationId), 8); vm.stopPrank(); } @@ -755,7 +759,8 @@ contract TimelockControllerTest is Test { SALT ); assertEq(vm.load(target, slot), bytes32(uint256(0))); - assertEq(timelockController.is_operation(operationId), false); + assertTrue(!timelockController.is_operation(operationId)); + assertEq(timelockController.get_operation_state(operationId), 1); assertEq(timelockController.get_timestamp(operationId), 0); vm.startPrank(PROPOSER_ONE); @@ -779,14 +784,16 @@ contract TimelockControllerTest is Test { SALT, MIN_DELAY ); - assertEq(timelockController.is_operation(operationId), true); + assertTrue(timelockController.is_operation(operationId)); assertEq( timelockController.get_timestamp(operationId), block.timestamp + MIN_DELAY ); vm.stopPrank(); + assertEq(timelockController.get_operation_state(operationId), 2); vm.warp(block.timestamp + MIN_DELAY); + assertEq(timelockController.get_operation_state(operationId), 4); vm.startPrank(EXECUTOR_ONE); vm.expectEmit(true, true, false, true); emit ITimelockController.CallExecuted( @@ -804,8 +811,9 @@ contract TimelockControllerTest is Test { SALT ); assertEq(vm.load(target, slot), value); - assertEq(timelockController.is_operation(operationId), true); + assertTrue(timelockController.is_operation(operationId)); assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); + assertEq(timelockController.get_operation_state(operationId), 8); vm.stopPrank(); } @@ -893,7 +901,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); - assertEq(timelockController.is_operation(operationId), true); + assertTrue(timelockController.is_operation(operationId)); vm.stopPrank(); operationId = timelockController.hash_operation( @@ -922,7 +930,7 @@ contract TimelockControllerTest is Test { SALT, MIN_DELAY + 1 ); - assertEq(timelockController.is_operation(operationId), true); + assertTrue(timelockController.is_operation(operationId)); vm.stopPrank(); } @@ -1824,1496 +1832,1418 @@ contract TimelockControllerTest is Test { vm.stopPrank(); } - // /*////////////////////////////////////////////////////////////// - // BATCH TESTS - // //////////////////////////////////////////////////////////////*/ - - // function testBatchComplete() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // assertEq(counter.number(), 0); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // assertEq(counter.number(), 1); - // } - - // function testBatchOperationAlreadyScheduled() public { - // address[] memory targets = new address[](1); - // targets[0] = address(0); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = new bytes(0); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.startPrank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.expectRevert("TimelockController: operation already scheduled"); - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - // } - - // function testBatchInsufficientDelay() public { - // address[] memory targets = new address[](1); - // targets[0] = address(0); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = new bytes(0); - - // vm.expectRevert("TimelockController: insufficient delay"); - // vm.prank(PROPOSER_ONE); - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - 1 - // ); - // } - - // function testBatchEqualAndGreaterMinimumDelay() public { - // address[] memory targets = new address[](1); - // targets[0] = address(0); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = new bytes(0); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // assertEq(timelockController.is_operation(batchedoperationId), true); - - // batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // bytes32("1") - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY + 1 - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // bytes32("1"), - // MIN_DELAY + 1 - // ); - - // assertEq(timelockController.is_operation(batchedoperationId), true); - // } - - // function testBatchMinimumDelayUpdate() public { - // address[] memory targets = new address[](1); - // targets[0] = address(0); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = new bytes(0); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // uint256 operationTimestampBefore = timelockController.get_timestamp( - // batchedoperationId - // ); - - // // Set a new delay value - // vm.prank(address(timelockController)); - // timelockController.update_delay(MIN_DELAY + 31 days); - - // // New delay value should only apply on future operations, not existing ones - // uint256 operationTimestampAfter = timelockController.get_timestamp( - // batchedoperationId - // ); - // assertEq(operationTimestampAfter, operationTimestampBefore); - // } - - // function testBatchOperationIsNotReady() public { - // address[] memory targets = new address[](1); - // targets[0] = address(0); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = new bytes(0); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY - 2 days); - - // vm.expectRevert("TimelockController: operation is not ready"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } - - // function testBatchPredecessorNotExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.startPrank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // bytes32 batchedoperationId2 = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // batchedoperationId, - // EMPTY_SALT - // ); - - // // Schedule dependent job - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId2, - // i, - // targets[i], - // values[i], - // payloads[i], - // batchedoperationId, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // batchedoperationId, - // EMPTY_SALT, - // MIN_DELAY - // ); - // vm.stopPrank(); - - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // batchedoperationId, - // EMPTY_SALT - // ); - // } - - // function testBatchPredecessorNotScheduled() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // vm.startPrank(PROPOSER_ONE); - - // // Prepare predecessor job - // bytes32 operationOneID = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // bytes32 operationOneID2 = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // operationOneID, - // EMPTY_SALT - // ); - - // // Schedule dependent job - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // operationOneID2, - // i, - // targets[i], - // values[i], - // payloads[i], - // operationOneID, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // operationOneID, - // EMPTY_SALT, - // MIN_DELAY - // ); - // vm.stopPrank(); - - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // operationOneID, - // EMPTY_SALT - // ); - // } - - // function testBatchPredecessorInvalid() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // // Prepare invalid predecessor - // bytes32 invalidPredecessor = 0xe685571b7e25a4a0391fb8daa09dc8d3fbb3382504525f89a2334fbbf8f8e92c; - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // invalidPredecessor, - // EMPTY_SALT - // ); - - // // Schedule dependent job - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // invalidPredecessor, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // invalidPredecessor, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // invalidPredecessor, - // EMPTY_SALT - // ); - // } - - // function testBatchTargetRevert() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.mockRevert.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // // Schedule a job where one target will revert - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY + 2 days); - // vm.expectRevert("Transaction reverted"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } - - // function testBatchPredecessorMultipleNotExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // // Schedule predecessor job - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // payloads[0] = abi.encodeWithSelector(Counter.setNumber.selector, 1); - - // // Schedule dependent job - // vm.prank(PROPOSER_ONE); - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // batchedoperationId, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // // Check that executing the dependent job reverts - // vm.warp(block.timestamp + MIN_DELAY + 2 days); - // vm.expectRevert("TimelockController: missing dependency"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // batchedoperationId, - // EMPTY_SALT - // ); - // } - - // function testBatchCancelFinished() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY + 1); - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // vm.prank(PROPOSER_ONE); - // vm.expectRevert("TimelockController: operation cannot be cancelled"); - // timelockController.cancel(batchedoperationId); - // } - - // function testBatchPendingIfNotYetExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // bool is_operation_pending = timelockController.is_operation_pending( - // batchedoperationId - // ); - // assertEq(is_operation_pending, true); - // } - - // function testBatchPendingIfExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // bool is_operation_pending = timelockController.is_operation_pending( - // batchedoperationId - // ); - // assertEq(is_operation_pending, false); - // } - - // function testBatchReadyOnTheExecutionTime() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // bool is_operation_ready = timelockController.is_operation_ready( - // batchedoperationId - // ); - // assertEq(is_operation_ready, true); - // } - - // function testBatchReadyAfterTheExecutionTime() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY + 1 days); - - // bool is_operation_ready = timelockController.is_operation_ready( - // batchedoperationId - // ); - // assertEq(is_operation_ready, true); - // } - - // function testBatchReadyBeforeTheExecutionTime() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY - 1 days); - - // bool is_operation_ready = timelockController.is_operation_ready( - // batchedoperationId - // ); - // assertEq(is_operation_ready, false); - // } - - // function testBatchHasBeenExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory values = new uint256[](1); - // values[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testHashOperationBatch() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq( + batchedOperationId, + keccak256( + abi.encode( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ) + ) + ); + } - // bool is_operation_ready = timelockController.is_operation_ready( - // batchedoperationId - // ); - // assertEq(is_operation_ready, false); + function testBatchScheduleAndExecuteWithEmptySalt() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(vm.load(target, slot), bytes32(uint256(0))); + assertTrue(!timelockController.is_operation(batchedOperationId)); + assertEq(timelockController.get_operation_state(batchedOperationId), 1); + assertEq(timelockController.get_timestamp(batchedOperationId), 0); - // bool is_operation_done = timelockController.is_operation_done( - // batchedoperationId - // ); - // assertEq(is_operation_done, true); - // } + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertTrue(timelockController.is_operation(batchedOperationId)); + assertEq( + timelockController.get_timestamp(batchedOperationId), + block.timestamp + MIN_DELAY + ); + vm.stopPrank(); - // function testBatchHasNotBeenExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); + assertEq(timelockController.get_operation_state(batchedOperationId), 2); + vm.warp(block.timestamp + MIN_DELAY); + assertEq(timelockController.get_operation_state(batchedOperationId), 4); + vm.startPrank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(vm.load(target, slot), value); + assertTrue(timelockController.is_operation(batchedOperationId)); + assertEq( + timelockController.get_timestamp(batchedOperationId), + DONE_TIMESTAMP + ); + assertEq(timelockController.get_operation_state(batchedOperationId), 8); + vm.stopPrank(); + } - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + function testBatchScheduleAndExecuteWithNonEmptySalt() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + SALT + ); + assertEq(vm.load(target, slot), bytes32(uint256(0))); + assertTrue(!timelockController.is_operation(batchedOperationId)); + assertEq(timelockController.get_operation_state(batchedOperationId), 1); + assertEq(timelockController.get_timestamp(batchedOperationId), 0); - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + vm.expectEmit(true, false, false, true); + emit ITimelockController.CallSalt(batchedOperationId, SALT); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + SALT, + MIN_DELAY + ); + assertTrue(timelockController.is_operation(batchedOperationId)); + assertEq( + timelockController.get_timestamp(batchedOperationId), + block.timestamp + MIN_DELAY + ); + vm.stopPrank(); - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + assertEq(timelockController.get_operation_state(batchedOperationId), 2); + vm.warp(block.timestamp + MIN_DELAY); + assertEq(timelockController.get_operation_state(batchedOperationId), 4); + vm.startPrank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + SALT + ); + assertEq(vm.load(target, slot), value); + assertTrue(timelockController.is_operation(batchedOperationId)); + assertEq( + timelockController.get_timestamp(batchedOperationId), + DONE_TIMESTAMP + ); + assertEq(timelockController.get_operation_state(batchedOperationId), 8); + vm.stopPrank(); + } - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + function testBatchOperationAlreadyScheduled() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.expectRevert("TimelockController: operation already scheduled"); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + } - // bool is_operation_done = timelockController.is_operation_done( - // batchedoperationId - // ); - // assertEq(is_operation_done, false); - // } + function testBatchInsufficientDelay() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + vm.expectRevert("TimelockController: insufficient delay"); + vm.prank(PROPOSER_ONE); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY - 1 + ); + } - // function testBatchTimestampHasNotBeenExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); + function testBatchEqualAndGreaterMinimumDelay() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertTrue(timelockController.is_operation(batchedOperationId)); + vm.stopPrank(); - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + SALT + ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + 1 + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + SALT, + MIN_DELAY + 1 + ); + assertTrue(timelockController.is_operation(batchedOperationId)); + vm.stopPrank(); + } - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testBatchMinimumDelayUpdate() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + uint256 operationTimestampBefore = timelockController.get_timestamp( + batchedOperationId + ); + vm.stopPrank(); - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedoperationId - // ); - // assertEq(operationTimestamp, block.timestamp + MIN_DELAY); - // } + vm.startPrank(address(timelockController)); + timelockController.update_delay(MIN_DELAY + 31 days); + uint256 operationTimestampAfter = timelockController.get_timestamp( + batchedOperationId + ); + assertEq(timelockController.get_minimum_delay(), MIN_DELAY + 31 days); + assertEq(operationTimestampAfter, operationTimestampBefore); + vm.stopPrank(); + } - // function testBatchTimestampHasBeenExecuted() public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); + function testBatchOperationIsNotReady() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + vm.warp(block.timestamp + MIN_DELAY - 2 days); + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + } - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testBatchPredecessorNotExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId1 = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + bytes32 batchedOperationId2 = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + batchedOperationId1, + SALT + ); - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId1, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId2, + i, + targets[i], + amounts[i], + payloads[i], + batchedOperationId1, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + batchedOperationId1, + SALT, + MIN_DELAY + ); + vm.stopPrank(); - // vm.warp(block.timestamp + MIN_DELAY); - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads, + batchedOperationId1, + SALT + ); + } - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedoperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // } + function testBatchPredecessorNotScheduled() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId1 = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + bytes32 batchedOperationId2 = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + batchedOperationId1, + SALT + ); - // function testFuzzBatchValue(uint256 amount) public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId2, + i, + targets[i], + amounts[i], + payloads[i], + batchedOperationId1, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + batchedOperationId1, + SALT, + MIN_DELAY + ); + vm.stopPrank(); - // uint256[] memory values = new uint256[](1); - // values[0] = amount; + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads, + batchedOperationId1, + SALT + ); + } - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + function testBatchPredecessorInvalid() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 invalidPredecessor = keccak256("Invalid Predecessor"); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + invalidPredecessor, + EMPTY_SALT + ); - // deal(address(timelockController), amount); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + invalidPredecessor, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + invalidPredecessor, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads, + invalidPredecessor, + EMPTY_SALT + ); + } - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + function testBatchTargetRevert() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes[] memory payloads1 = new bytes[](1); + payloads1[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionRevertsWithReason.selector + ); + bytes[] memory payloads2 = new bytes[](1); + payloads2[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionRevertsWithEmptyReason.selector + ); + bytes32 batchedOperationId1 = timelockController.hash_operation_batch( + targets, + amounts, + payloads1, + NO_PREDECESSOR, + EMPTY_SALT + ); + bytes32 batchedOperationId2 = timelockController.hash_operation_batch( + targets, + amounts, + payloads2, + NO_PREDECESSOR, + SALT + ); - // vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId1, + i, + targets[i], + amounts[i], + payloads1[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads1, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId2, + i, + targets[i], + amounts[i], + payloads2[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads2, + NO_PREDECESSOR, + SALT, + MIN_DELAY + ); + vm.stopPrank(); - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("CallReceiverMock: reverting"); + vm.startPrank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads1, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.expectRevert("TimelockController: underlying transaction reverted"); + timelockController.execute_batch( + targets, + amounts, + payloads2, + NO_PREDECESSOR, + SALT + ); + vm.stopPrank(); + } - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedoperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(address(counter).balance, values[0]); - // } + function testBatchPredecessorMultipleNotExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // function testBatchERC1155() public { - // ERC1155Mock erc1155 = new ERC1155Mock(""); - // erc1155.mint(address(timelockController), 1, 1, new bytes(0)); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); - // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunction.selector + ); + vm.startPrank(PROPOSER_ONE); + timelockController.schedule_batch( + targets, + amounts, + payloads, + batchedOperationId, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // address[] memory targets = new address[](1); - // targets[0] = address(erc1155); + vm.warp(block.timestamp + MIN_DELAY + 2 days); + vm.expectRevert("TimelockController: missing dependency"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads, + batchedOperationId, + EMPTY_SALT + ); + } - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + function testBatchCancelFinished() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector( - // ERC1155Mock.burn.selector, - // address(timelockController), - // 1, - // 1 - // ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.warp(block.timestamp + MIN_DELAY + 1); + vm.startPrank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + vm.stopPrank(); - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + vm.prank(PROPOSER_ONE); + vm.expectRevert("TimelockController: operation cannot be cancelled"); + timelockController.cancel(batchedOperationId); + } - // vm.warp(block.timestamp + MIN_DELAY); + function testBatchPendingIfNotYetExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertTrue(timelockController.is_operation_pending(batchedOperationId)); + vm.stopPrank(); + } - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedoperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); - // } + function testBatchPendingIfExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // function testBatchERC721() public { - // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); - // erc721.mint(address(timelockController), 1); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // assertEq(erc721.balanceOf(address(timelockController)), 1); + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertTrue( + !timelockController.is_operation_pending(batchedOperationId) + ); + vm.stopPrank(); + } - // address[] memory targets = new address[](1); - // targets[0] = address(erc721); + function testBatchReadyOnTheExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.warp(block.timestamp + MIN_DELAY); + assertTrue(timelockController.is_operation_ready(batchedOperationId)); + vm.stopPrank(); + } - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); + function testBatchReadyAfterTheExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // bytes32 batchedoperationId = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.warp(block.timestamp + MIN_DELAY + 1 days); + assertTrue(timelockController.is_operation_ready(batchedOperationId)); + vm.stopPrank(); + } - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); + function testBatchReadyBeforeTheExecutionTime() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.warp(block.timestamp + MIN_DELAY - 1 days); + assertTrue(!timelockController.is_operation_ready(batchedOperationId)); + vm.stopPrank(); + } - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedoperationId, - // i, - // targets[i], - // values[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); + function testBatchHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedoperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc721.balanceOf(address(timelockController)), 0); - // } + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // /*////////////////////////////////////////////////////////////// - // SANITY CHECKS TESTS - // //////////////////////////////////////////////////////////////*/ + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertTrue(!timelockController.is_operation_ready(batchedOperationId)); + assertTrue(timelockController.is_operation_done(batchedOperationId)); + vm.stopPrank(); + } - // function testReturnsLaterMinimumDelayForCalls() public { - // uint256 newMinDelay = 31 days; - // _laterDelay(newMinDelay); - // uint256 minDelay = timelockController.get_minimum_delay(); - // assertEq(minDelay, newMinDelay); - // } + function testBatchHasNotBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // function testInvalidOperation() public { - // bool is_operation = timelockController.is_operation(bytes32("non-op")); - // assertEq(is_operation, false); - // } + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + assertTrue(!timelockController.is_operation_done(batchedOperationId)); + vm.stopPrank(); + } - // // Hash calculation - // function testHashOperationBatch() public { - // address[] memory targets = new address[](2); - // targets[0] = address(this); - // targets[1] = address(this); + function testBatchTimestampHasNotBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // uint256[] memory values = new uint256[](2); - // values[0] = 0; - // values[1] = 1; + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + uint256 operationTimestamp = timelockController.get_timestamp( + batchedOperationId + ); + assertEq(operationTimestamp, block.timestamp + MIN_DELAY); + vm.stopPrank(); + } - // bytes[] memory payloads = new bytes[](2); - // payloads[0] = abi.encodeWithSelector( - // this.testHashOperationBatch.selector - // ); - // payloads[1] = abi.encodeWithSelector( - // this.testHashOperationBatch.selector - // ); + function testBatchTimestampHasBeenExecuted() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); - // bytes32 hashedOperation = timelockController.hash_operation_batch( - // targets, - // values, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // bytes32 expectedHash = keccak256( - // abi.encode(targets, values, payloads, NO_PREDECESSOR, EMPTY_SALT) - // ); - // assertEq(hashedOperation, expectedHash); - // } + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); - // function testHashOperation() public { - // address target = address(this); - // uint256 amount = 1; - // bytes memory payload = abi.encodeWithSelector( - // this.testHashOperationBatch.selector - // ); + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq( + timelockController.get_timestamp(batchedOperationId), + DONE_TIMESTAMP + ); + vm.stopPrank(); + } - // bytes32 hashedOperation = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // bytes32 expectedHash = keccak256( - // abi.encode(target, amount, payload, NO_PREDECESSOR, EMPTY_SALT) - // ); - // assertEq(hashedOperation, expectedHash); - // } + function testReturnsLaterMinimumDelayForCalls() public { + uint256 newMinDelay = 31 days; + vm.startPrank(timelockControllerAddr); + vm.expectEmit(true, true, false, false); + emit ITimelockController.MinimumDelayChange( + timelockController.get_minimum_delay(), + newMinDelay + ); + timelockController.update_delay(newMinDelay); + vm.stopPrank(); + uint256 minDelay = timelockController.get_minimum_delay(); + assertEq(minDelay, newMinDelay); + } - // // TODO: Add NFTs tests + function testInvalidOperation() public { + assertTrue(!timelockController.is_operation(keccak256("Invalid"))); + } // /*////////////////////////////////////////////////////////////// // PERMISSION TESTS @@ -3331,14 +3261,14 @@ contract TimelockControllerTest is Test { // function testAdminCantBatchSchedule() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.expectRevert("AccessControl: account is missing role"); // vm.prank(ADMIN); // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT, @@ -3361,14 +3291,14 @@ contract TimelockControllerTest is Test { // function testAdminCantBatchExecute() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.expectRevert("AccessControl: account is missing role"); // vm.prank(ADMIN); // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT @@ -3397,13 +3327,13 @@ contract TimelockControllerTest is Test { // function testProposerCanBatchSchedule() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.prank(PROPOSER_ONE); // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT, @@ -3413,7 +3343,7 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_TWO); // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // bytes32("1"), @@ -3445,14 +3375,14 @@ contract TimelockControllerTest is Test { // function testProposerCantBatchExecute() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.expectRevert("AccessControl: account is missing role"); // vm.prank(PROPOSER_ONE); // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT @@ -3462,7 +3392,7 @@ contract TimelockControllerTest is Test { // vm.prank(PROPOSER_TWO); // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // bytes32("1") @@ -3505,14 +3435,14 @@ contract TimelockControllerTest is Test { // function testExecutorCantBatchSchedule() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.expectRevert("AccessControl: account is missing role"); // vm.prank(EXECUTOR_ONE); // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT, @@ -3523,7 +3453,7 @@ contract TimelockControllerTest is Test { // vm.prank(EXECUTOR_TWO); // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // bytes32("1"), @@ -3557,14 +3487,14 @@ contract TimelockControllerTest is Test { // function testExecutorCanBatchExecute() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.expectRevert("TimelockController: operation is not ready"); // vm.prank(EXECUTOR_ONE); // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT @@ -3574,7 +3504,7 @@ contract TimelockControllerTest is Test { // vm.prank(EXECUTOR_TWO); // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // bytes32("1") @@ -3617,14 +3547,14 @@ contract TimelockControllerTest is Test { // function testStrangerCantBatchSchedule() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.expectRevert("AccessControl: account is missing role"); // vm.prank(STRANGER); // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT, @@ -3647,14 +3577,14 @@ contract TimelockControllerTest is Test { // function testStrangerCantBatchExecute() public { // address[] memory targets = new address[](0); - // uint256[] memory values = new uint256[](0); + // uint256[] memory amounts = new uint256[](0); // bytes[] memory payloads = new bytes[](0); // vm.expectRevert("AccessControl: account is missing role"); // vm.prank(STRANGER); // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT @@ -3699,15 +3629,15 @@ contract TimelockControllerTest is Test { // address[] memory targets = new address[](1); // targets[0] = address(erc721); - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + // uint256[] memory amounts = new uint256[](1); + // amounts[0] = 0; // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); - // bytes32 batchedoperationId = timelockController.hash_operation_batch( + // bytes32 batchedOperationId = timelockController.hash_operation_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT @@ -3717,10 +3647,10 @@ contract TimelockControllerTest is Test { // for (uint256 i = 0; i < targets.length; ++i) { // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedoperationId, + // batchedOperationId, // i, // targets[i], - // values[i], + // amounts[i], // payloads[i], // NO_PREDECESSOR, // MIN_DELAY @@ -3728,7 +3658,7 @@ contract TimelockControllerTest is Test { // } // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT, @@ -3741,23 +3671,23 @@ contract TimelockControllerTest is Test { // for (uint256 i = 0; i < targets.length; ++i) { // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedoperationId, + // batchedOperationId, // i, // targets[i], - // values[i], + // amounts[i], // payloads[i] // ); // } // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT // ); // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedoperationId + // batchedOperationId // ); // assertEq(operationTimestamp, DONE_TIMESTAMP); // assertEq(erc721.balanceOf(address(timelockController)), 0); @@ -3772,8 +3702,86 @@ contract TimelockControllerTest is Test { // address[] memory targets = new address[](1); // targets[0] = address(erc1155); - // uint256[] memory values = new uint256[](1); - // values[0] = 0; + // uint256[] memory amounts = new uint256[](1); + // amounts[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector( + // ERC1155Mock.burn.selector, + // address(timelockController), + // 1, + // 1 + // ); + + // bytes32 batchedOperationId = timelockController.hash_operation_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallScheduled( + // batchedOperationId, + // i, + // targets[i], + // amounts[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallExecuted( + // batchedOperationId, + // i, + // targets[i], + // amounts[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationId + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); + // } + + // function testBatchERC1155() public { + // ERC1155Mock erc1155 = new ERC1155Mock(""); + // erc1155.mint(address(timelockController), 1, 1, new bytes(0)); + + // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc1155); + + // uint256[] memory amounts = new uint256[](1); + // amounts[0] = 0; // bytes[] memory payloads = new bytes[](1); // payloads[0] = abi.encodeWithSelector( @@ -3783,9 +3791,9 @@ contract TimelockControllerTest is Test { // 1 // ); - // bytes32 batchedoperationId = timelockController.hash_operation_batch( + // bytes32 batchedOperationId = timelockController.hash_operation_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT @@ -3795,10 +3803,10 @@ contract TimelockControllerTest is Test { // for (uint256 i = 0; i < targets.length; ++i) { // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallScheduled( - // batchedoperationId, + // batchedOperationId, // i, // targets[i], - // values[i], + // amounts[i], // payloads[i], // NO_PREDECESSOR, // MIN_DELAY @@ -3806,7 +3814,7 @@ contract TimelockControllerTest is Test { // } // timelockController.schedule_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT, @@ -3819,28 +3827,101 @@ contract TimelockControllerTest is Test { // for (uint256 i = 0; i < targets.length; ++i) { // vm.expectEmit(true, true, false, true); // emit ITimelockController.CallExecuted( - // batchedoperationId, + // batchedOperationId, // i, // targets[i], - // values[i], + // amounts[i], // payloads[i] // ); // } // timelockController.execute_batch( // targets, - // values, + // amounts, // payloads, // NO_PREDECESSOR, // EMPTY_SALT // ); // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedoperationId + // batchedOperationId // ); // assertEq(operationTimestamp, DONE_TIMESTAMP); // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); // } + // function testBatchERC721() public { + // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); + // erc721.mint(address(timelockController), 1); + + // assertEq(erc721.balanceOf(address(timelockController)), 1); + + // address[] memory targets = new address[](1); + // targets[0] = address(erc721); + + // uint256[] memory amounts = new uint256[](1); + // amounts[0] = 0; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); + + // bytes32 batchedOperationId = timelockController.hash_operation_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallScheduled( + // batchedOperationId, + // i, + // targets[i], + // amounts[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallExecuted( + // batchedOperationId, + // i, + // targets[i], + // amounts[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationId + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(erc721.balanceOf(address(timelockController)), 0); + // } + // function testFuzzOperationValue(uint256 amount) public { // address target = address(counter); // bytes memory payload = abi.encodeWithSelector( @@ -3902,6 +3983,76 @@ contract TimelockControllerTest is Test { // assertEq(operationTimestamp, DONE_TIMESTAMP); // assertEq(address(counter).balance, amount); // } + + // function testFuzzBatchValue(uint256 amount) public { + // address[] memory targets = new address[](1); + // targets[0] = address(counter); + + // uint256[] memory amounts = new uint256[](1); + // amounts[0] = amount; + + // bytes[] memory payloads = new bytes[](1); + // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); + + // deal(address(timelockController), amount); + + // bytes32 batchedOperationId = timelockController.hash_operation_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // vm.prank(PROPOSER_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallScheduled( + // batchedOperationId, + // i, + // targets[i], + // amounts[i], + // payloads[i], + // NO_PREDECESSOR, + // MIN_DELAY + // ); + // } + // timelockController.schedule_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT, + // MIN_DELAY + // ); + + // vm.warp(block.timestamp + MIN_DELAY); + + // vm.prank(EXECUTOR_ONE); + // for (uint256 i = 0; i < targets.length; ++i) { + // vm.expectEmit(true, true, false, true); + // emit ITimelockController.CallExecuted( + // batchedOperationId, + // i, + // targets[i], + // amounts[i], + // payloads[i] + // ); + // } + // timelockController.execute_batch( + // targets, + // amounts, + // payloads, + // NO_PREDECESSOR, + // EMPTY_SALT + // ); + + // uint256 operationTimestamp = timelockController.get_timestamp( + // batchedOperationId + // ); + // assertEq(operationTimestamp, DONE_TIMESTAMP); + // assertEq(address(counter).balance, amounts[0]); + // } } // contract TimelockControllerInvariants is Test { diff --git a/test/governance/interfaces/ITimelockController.sol b/test/governance/interfaces/ITimelockController.sol index b2e85177..cfd7ac39 100644 --- a/test/governance/interfaces/ITimelockController.sol +++ b/test/governance/interfaces/ITimelockController.sol @@ -10,13 +10,6 @@ interface ITimelockController is IERC1155Receiver, IAccessControl { - enum OperationState { - Unset, - Waiting, - Ready, - Done - } - event CallScheduled( bytes32 indexed id, uint256 indexed index, @@ -73,9 +66,12 @@ interface ITimelockController is function is_operation_done(bytes32 id) external view returns (bool); - function get_operation_state( - bytes32 id - ) external view returns (OperationState); + /** + * @dev As Enums are handled differently in Vyper and Solidity, we return + * the directly underlying Vyper type `uint256` (instead of `OperationState`) + * for Enums for ease of testing. + */ + function get_operation_state(bytes32 id) external view returns (uint256); function hash_operation( address target, From 47215538ba787670ed71c4b54ca678ff7ecb5f14 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Wed, 31 Jan 2024 12:18:49 +0100 Subject: [PATCH 42/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/governance/TimelockController.t.sol | 2031 ++++++++++---------- test/governance/mocks/CallReceiverMock.sol | 2 +- 2 files changed, 964 insertions(+), 1069 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 227a70b5..7f670316 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -12,6 +12,8 @@ import {ERC721ReceiverMock} from "../tokens/mocks/ERC721ReceiverMock.sol"; import {ERC1155ReceiverMock} from "../tokens/mocks/ERC1155ReceiverMock.sol"; import {CallReceiverMock} from "./mocks/CallReceiverMock.sol"; +import {IERC721Extended} from "../tokens/interfaces/IERC721Extended.sol"; +import {IERC1155Extended} from "../tokens/interfaces/IERC1155Extended.sol"; import {ITimelockController} from "./interfaces/ITimelockController.sol"; contract TimelockControllerTest is Test { @@ -51,10 +53,12 @@ contract TimelockControllerTest is Test { ITimelockController private timelockController; ITimelockController private timelockControllerInitialEventEmptyAdmin; ITimelockController private timelockControllerInitialEventNonEmptyAdmin; + IERC721Extended private erc721Mock; + IERC1155Extended private erc1155Mock; address private deployer = address(vyperDeployer); address private self = address(this); - address private zeroAddress = address(0); + address private zeroAddress = zeroAddress; address private target = address(callReceiverMock); address private timelockControllerAddr; address private timelockControllerInitialEventEmptyAdminAddr; @@ -237,7 +241,7 @@ contract TimelockControllerTest is Test { MIN_DELAY, proposers_, executors_, - address(0) + zeroAddress ); vm.expectEmit(true, true, true, false); emit IAccessControl.RoleGranted( @@ -3245,1071 +3249,962 @@ contract TimelockControllerTest is Test { assertTrue(!timelockController.is_operation(keccak256("Invalid"))); } - // /*////////////////////////////////////////////////////////////// - // PERMISSION TESTS - // //////////////////////////////////////////////////////////////*/ - - // // Timelock - - // function testRevertWhenNotTimelock() public { - // vm.expectRevert("TimelockController: caller must be timelock"); - // vm.prank(STRANGER); - // timelockController.update_delay(3 days); - // } - - // // Admin - - // function testAdminCantBatchSchedule() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(ADMIN); - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - // } - - // function testAdminCantSchedule() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(ADMIN); - // timelockController.schedule( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - // } - - // function testAdminCantBatchExecute() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(ADMIN); - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } - - // function testAdminCantExecute() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(ADMIN); - // timelockController.execute( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } - - // function testAdminCantCancel() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(ADMIN); - // timelockController.cancel(EMPTY_SALT); - // } - - // // Proposer - - // function testProposerCanBatchSchedule() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.prank(PROPOSER_ONE); - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.prank(PROPOSER_TWO); - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // bytes32("1"), - // MIN_DELAY - // ); - // } - - // function testProposerCanSchedule() public { - // vm.prank(PROPOSER_ONE); - // timelockController.schedule( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.prank(PROPOSER_TWO); - // timelockController.schedule( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // bytes32("1"), - // MIN_DELAY - // ); - // } - - // function testProposerCantBatchExecute() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(PROPOSER_ONE); - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(PROPOSER_TWO); - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // bytes32("1") - // ); - // } - - // function testProposerCantExecute() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(PROPOSER_ONE); - // timelockController.execute( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(PROPOSER_TWO); - // timelockController.execute( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // bytes32("1") - // ); - // } - - // function testProposerCanCancel() public { - // vm.expectRevert("TimelockController: operation cannot be cancelled"); - // vm.prank(PROPOSER_ONE); - // timelockController.cancel(EMPTY_SALT); - - // vm.expectRevert("TimelockController: operation cannot be cancelled"); - // vm.prank(PROPOSER_TWO); - // timelockController.cancel(EMPTY_SALT); - // } - - // // Executor - - // function testExecutorCantBatchSchedule() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(EXECUTOR_ONE); - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(EXECUTOR_TWO); - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // bytes32("1"), - // MIN_DELAY - // ); - // } - - // function testExecutorCantSchedule() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(EXECUTOR_ONE); - // timelockController.schedule( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(EXECUTOR_TWO); - // timelockController.schedule( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // bytes32("1"), - // MIN_DELAY - // ); - // } - - // function testExecutorCanBatchExecute() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.expectRevert("TimelockController: operation is not ready"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.expectRevert("TimelockController: operation is not ready"); - // vm.prank(EXECUTOR_TWO); - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // bytes32("1") - // ); - // } - - // function testExecutorCanExecute() public { - // vm.expectRevert("TimelockController: operation is not ready"); - // vm.prank(EXECUTOR_ONE); - // timelockController.execute( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.expectRevert("TimelockController: operation is not ready"); - // vm.prank(EXECUTOR_TWO); - // timelockController.execute( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // bytes32("1") - // ); - // } - - // function testExecutorCantCancel() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(EXECUTOR_ONE); - // timelockController.cancel(EMPTY_SALT); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(EXECUTOR_TWO); - // timelockController.cancel(EMPTY_SALT); - // } - - // // Stanger - - // function testStrangerCantBatchSchedule() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(STRANGER); - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - // } - - // function testStrangerCantSchedule() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(STRANGER); - // timelockController.schedule( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - // } - - // function testStrangerCantBatchExecute() public { - // address[] memory targets = new address[](0); - // uint256[] memory amounts = new uint256[](0); - // bytes[] memory payloads = new bytes[](0); - - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(STRANGER); - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } - - // function testStrangerCantExecute() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(STRANGER); - // timelockController.execute( - // address(0), - // 0, - // new bytes(0), - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - // } - - // function testStrangerCantCancel() public { - // vm.expectRevert("AccessControl: account is missing role"); - // vm.prank(STRANGER); - // timelockController.cancel(EMPTY_SALT); - // } - - // // TODO: Move this somewhere in correct place - // function testCancellerCanCancelOperation() public { - // bytes32 operationId = _cancelOperation(); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(true, false, false, false); - // emit ITimelockController.Cancelled(operationId); - // timelockController.cancel(operationId); - // assertTrue(!timelockController.is_operation(operationId)); - // } - - // function testOperationERC721() public { - // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); - // erc721.mint(address(timelockController), 1); - - // assertEq(erc721.balanceOf(address(timelockController)), 1); - - // address[] memory targets = new address[](1); - // targets[0] = address(erc721); - - // uint256[] memory amounts = new uint256[](1); - // amounts[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); - - // bytes32 batchedOperationId = timelockController.hash_operation_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc721.balanceOf(address(timelockController)), 0); - // } - - // function testOperationERC1155() public { - // ERC1155Mock erc1155 = new ERC1155Mock(""); - // erc1155.mint(address(timelockController), 1, 1, new bytes(0)); - - // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); - - // address[] memory targets = new address[](1); - // targets[0] = address(erc1155); - - // uint256[] memory amounts = new uint256[](1); - // amounts[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector( - // ERC1155Mock.burn.selector, - // address(timelockController), - // 1, - // 1 - // ); - - // bytes32 batchedOperationId = timelockController.hash_operation_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); - // } - - // function testBatchERC1155() public { - // ERC1155Mock erc1155 = new ERC1155Mock(""); - // erc1155.mint(address(timelockController), 1, 1, new bytes(0)); - - // assertEq(erc1155.balanceOf(address(timelockController), 1), 1); - - // address[] memory targets = new address[](1); - // targets[0] = address(erc1155); - - // uint256[] memory amounts = new uint256[](1); - // amounts[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector( - // ERC1155Mock.burn.selector, - // address(timelockController), - // 1, - // 1 - // ); - - // bytes32 batchedOperationId = timelockController.hash_operation_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc1155.balanceOf(address(timelockController), 1), 0); - // } - - // function testBatchERC721() public { - // ERC721Mock erc721 = new ERC721Mock("SYMBOL", "SML"); - // erc721.mint(address(timelockController), 1); - - // assertEq(erc721.balanceOf(address(timelockController)), 1); - - // address[] memory targets = new address[](1); - // targets[0] = address(erc721); - - // uint256[] memory amounts = new uint256[](1); - // amounts[0] = 0; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(ERC721Mock.burn.selector, 1); - - // bytes32 batchedOperationId = timelockController.hash_operation_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(erc721.balanceOf(address(timelockController)), 0); - // } - - // function testFuzzOperationValue(uint256 amount) public { - // address target = address(counter); - // bytes memory payload = abi.encodeWithSelector( - // Counter.increment.selector - // ); - - // bytes32 operationId = timelockController.hash_operation( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // deal(address(timelockController), amount); - - // vm.prank(PROPOSER_ONE); - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // operationId, - // 0, - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // timelockController.schedule( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // operationId, - // 0, - // target, - // amount, - // payload - // ); - // timelockController.execute( - // target, - // amount, - // payload, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // operationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(address(counter).balance, amount); - // } - - // function testFuzzBatchValue(uint256 amount) public { - // address[] memory targets = new address[](1); - // targets[0] = address(counter); - - // uint256[] memory amounts = new uint256[](1); - // amounts[0] = amount; - - // bytes[] memory payloads = new bytes[](1); - // payloads[0] = abi.encodeWithSelector(Counter.increment.selector); - - // deal(address(timelockController), amount); - - // bytes32 batchedOperationId = timelockController.hash_operation_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // vm.prank(PROPOSER_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallScheduled( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i], - // NO_PREDECESSOR, - // MIN_DELAY - // ); - // } - // timelockController.schedule_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT, - // MIN_DELAY - // ); - - // vm.warp(block.timestamp + MIN_DELAY); - - // vm.prank(EXECUTOR_ONE); - // for (uint256 i = 0; i < targets.length; ++i) { - // vm.expectEmit(true, true, false, true); - // emit ITimelockController.CallExecuted( - // batchedOperationId, - // i, - // targets[i], - // amounts[i], - // payloads[i] - // ); - // } - // timelockController.execute_batch( - // targets, - // amounts, - // payloads, - // NO_PREDECESSOR, - // EMPTY_SALT - // ); - - // uint256 operationTimestamp = timelockController.get_timestamp( - // batchedOperationId - // ); - // assertEq(operationTimestamp, DONE_TIMESTAMP); - // assertEq(address(counter).balance, amounts[0]); - // } + function testRevertWhenNotTimelock() public { + vm.expectRevert("TimelockController: caller must be timelock"); + vm.prank(STRANGER); + timelockController.update_delay(3 days); + } + + function testAdminCantBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(self); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + } + + function testAdminCantSchedule() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(self); + timelockController.schedule( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + } + + function testAdminCantBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(self); + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + } + + function testAdminCantExecute() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(self); + timelockController.execute( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT + ); + } + + function testAdminCantCancel() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(self); + timelockController.cancel(EMPTY_SALT); + } + + function testProposerCanBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + vm.startPrank(PROPOSER_ONE); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + vm.prank(PROPOSER_TWO); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + SALT, + MIN_DELAY + ); + vm.stopPrank(); + } + + function testProposerCanSchedule() public { + vm.startPrank(PROPOSER_ONE); + timelockController.schedule( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + vm.startPrank(PROPOSER_TWO); + timelockController.schedule( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + bytes32("1"), + MIN_DELAY + ); + vm.stopPrank(); + } + + function testProposerCantBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_TWO); + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + bytes32("1") + ); + } + + function testProposerCantExecute() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_ONE); + timelockController.execute( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(PROPOSER_TWO); + timelockController.execute( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + bytes32("1") + ); + } + + function testProposerCanCancel() public { + vm.expectRevert("TimelockController: operation cannot be cancelled"); + vm.prank(PROPOSER_ONE); + timelockController.cancel(EMPTY_SALT); + + vm.expectRevert("TimelockController: operation cannot be cancelled"); + vm.prank(PROPOSER_TWO); + timelockController.cancel(EMPTY_SALT); + } + + function testExecutorCantBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_ONE); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_TWO); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + bytes32("1"), + MIN_DELAY + ); + } + + function testExecutorCantSchedule() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_ONE); + timelockController.schedule( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_TWO); + timelockController.schedule( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + bytes32("1"), + MIN_DELAY + ); + } + + function testExecutorCanBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_TWO); + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + bytes32("1") + ); + } + + function testExecutorCanExecute() public { + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_ONE); + timelockController.execute( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.expectRevert("TimelockController: operation is not ready"); + vm.prank(EXECUTOR_TWO); + timelockController.execute( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + bytes32("1") + ); + } + + function testExecutorCantCancel() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_ONE); + timelockController.cancel(EMPTY_SALT); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(EXECUTOR_TWO); + timelockController.cancel(EMPTY_SALT); + } + + function testStrangerCantBatchSchedule() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + } + + function testStrangerCantSchedule() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.schedule( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + } + + function testStrangerCantBatchExecute() public { + address[] memory targets = new address[](0); + uint256[] memory amounts = new uint256[](0); + bytes[] memory payloads = new bytes[](0); + + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + } + + function testStrangerCantExecute() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.execute( + zeroAddress, + 0, + new bytes(0), + NO_PREDECESSOR, + EMPTY_SALT + ); + } + + function testStrangerCantCancel() public { + vm.expectRevert("AccessControl: account is missing role"); + vm.prank(STRANGER); + timelockController.cancel(EMPTY_SALT); + } + + function testCancellerCanCancelOperation() public { + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.expectEmit(true, false, false, false); + emit ITimelockController.Cancelled(batchedOperationId); + timelockController.cancel(batchedOperationId); + assertTrue(!timelockController.is_operation(batchedOperationId)); + vm.stopPrank(); + } + + function testHandleERC721() public { + bytes memory args = abi.encode( + "MyNFT", + "WAGMI", + "https://www.wagmi.xyz/", + "MyNFT", + "1" + ); + erc721Mock = IERC721Extended( + vyperDeployer.deployContract("src/tokens/", "ERC721", args) + ); + vm.startPrank(deployer); + erc721Mock.safe_mint(timelockControllerAddr, "my_awesome_nft_uri_1"); + assertEq(erc721Mock.balanceOf(timelockControllerAddr), 1); + vm.stopPrank(); + + address[] memory targets = new address[](1); + targets[0] = address(erc721Mock); + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector(erc721Mock.burn.selector, 0); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.startPrank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(timelockController.get_timestamp( + batchedOperationId + ), DONE_TIMESTAMP); + assertEq(erc721Mock.balanceOf(timelockControllerAddr), 0); + } + + function testHandleERC1155() public { + bytes memory args = abi.encode("https://www.wagmi.xyz/"); + erc1155Mock = IERC1155Extended( + vyperDeployer.deployContract("src/tokens/", "ERC1155", args) + ); + + uint256[] memory ids = new uint256[](2); + uint256[] memory tokenAmounts = new uint256[](2); + ids[0] = 1; + ids[1] = 2; + tokenAmounts[0] = 1; + tokenAmounts[1] = 2; + + vm.startPrank(deployer); + erc1155Mock.safe_mint(timelockControllerAddr, 0, 1, new bytes(0)); + erc1155Mock.safe_mint_batch(timelockControllerAddr, ids, tokenAmounts, new bytes(0)); + assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 0), 1); + assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 1), 1); + assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 2), 2); + vm.stopPrank(); + + address[] memory targets = new address[](1); + targets[0] = address(erc1155Mock); + uint256[] memory amounts = new uint256[](1); + amounts[0] = 0; + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + erc1155Mock.burn.selector, + timelockControllerAddr, + 0, + 1 + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + + assertEq(timelockController.get_timestamp( + batchedOperationId + ), DONE_TIMESTAMP); + assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 0), 0); + } + + function testFuzzOperationValue(uint256 amount) public { + amount = bound(amount, 0, type(uint64).max); + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes memory payload = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 operationId = timelockController.hash_operation( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + deal(timelockControllerAddr, amount); + + vm.prank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + target, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + vm.prank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + target, + amount, + payload + ); + timelockController.execute( + target, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(timelockController.get_timestamp( + operationId + ), DONE_TIMESTAMP); + assertEq(address(callReceiverMock).balance, amount); + } + + function testFuzzBatchValue(uint256 amount) public { + amount = bound(amount, 0, type(uint64).max); + address[] memory targets = new address[](1); + targets[0] = target; + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount; + bytes32 slot = bytes32(uint256(1337)); + bytes32 value = bytes32(uint256(6699)); + bytes[] memory payloads = new bytes[](1); + payloads[0] = abi.encodeWithSelector( + callReceiverMock.mockFunctionWritesStorage.selector, + slot, + value + ); + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + deal(timelockControllerAddr, amount); + + vm.prank(PROPOSER_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i], + NO_PREDECESSOR, + MIN_DELAY + ); + } + timelockController.schedule_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + + vm.warp(block.timestamp + MIN_DELAY); + + vm.prank(EXECUTOR_ONE); + for (uint256 i = 0; i < targets.length; ++i) { + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + batchedOperationId, + i, + targets[i], + amounts[i], + payloads[i] + ); + } + timelockController.execute_batch( + targets, + amounts, + payloads, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(timelockController.get_timestamp( + batchedOperationId + ), DONE_TIMESTAMP); + assertEq(address(callReceiverMock).balance, amounts[0]); + } +} + +contract TimelockControllerInvariants is Test { + VyperDeployer private vyperDeployer = new VyperDeployer(); + + ITimelockController private timelockController; + TimelockControllerHandler private timelockControllerHandler; + + function setUp() public { + address[] memory proposers = new address[](1); + proposers[0] = address(this); + + address[] memory executors = new address[](1); + executors[0] = address(this); + + uint256 minDelay = 2 days; + + bytes memory args = abi.encode( + minDelay, + proposers, + executors, + address(this) + ); + timelockController = ITimelockController( + payable( + vyperDeployer.deployContract( + "src/governance/", + "TimelockController", + args + ) + ) + ); + + timelockControllerHandler = new TimelockControllerHandler( + timelockController, + minDelay, + proposers, + executors, + address(this) + ); + + // Select the selectors to use for fuzzing. + bytes4[] memory selectors = new bytes4[](3); + selectors[0] = TimelockControllerHandler.schedule.selector; + selectors[1] = TimelockControllerHandler.execute.selector; + selectors[2] = TimelockControllerHandler.cancel.selector; + + // Set the target selector. + targetSelector( + FuzzSelector({ + addr: address(timelockControllerHandler), + selectors: selectors + }) + ); + + // Set the target contract. + targetContract(address(timelockControllerHandler)); + } + + // Number of pending transactions cannot exceed executed transactions + function invariantExecutedLessThanOrEqualToPending() public { + assertLe( + timelockControllerHandler.execute_count(), + timelockControllerHandler.schedule_count() + ); + } + + // Number of proposals executed must match the count number. + function invariantProposalsExecutedMatchCount() public { + assertEq( + timelockControllerHandler.execute_count(), + timelockControllerHandler.counter() + ); + } + + // Proposals can only be scheduled and executed once + function invariantOnceProposalExecution() public { + uint256[] memory executed = timelockControllerHandler.getExecuted(); + // Loop over all executed proposals. + for (uint256 i = 0; i < executed.length; ++i) { + // Check that the executed proposal cannot be executed again. + vm.expectRevert("TimelockController: operation is not ready"); + timelockController.execute( + address(timelockControllerHandler), + 0, + abi.encodeWithSelector( + TimelockControllerHandler.increment.selector + ), + bytes32(""), + bytes32(executed[i]) + ); + } + } + + // Sum of number of executed proposals and cancelled proposals must be less or equal to the amount of proposals scheduled. + function invariantSumOfProposals() public { + assertLe( + timelockControllerHandler.cancel_count() + + timelockControllerHandler.execute_count(), + timelockControllerHandler.schedule_count() + ); + } + + // Executed proposals cannot be cancelled + function invariantExecutedProposalCancellation() public { + uint256[] memory executed = timelockControllerHandler.getExecuted(); + // Loop over all executed proposals. + for (uint256 i = 0; i < executed.length; ++i) { + // Check that the executed proposal cannot be cancelled. + vm.expectRevert( + "TimelockController: operation cannot be cancelled" + ); + timelockController.cancel(bytes32(executed[i])); + } + } + + // Executing a proposal that has been cancelled is not possible + function invariantExecutingCancelledProposal() public { + uint256[] memory cancelled = timelockControllerHandler.getCancelled(); + // Loop over all cancelled proposals. + for (uint256 i = 0; i < cancelled.length; ++i) { + // Check that the cancelled proposal cannot be executed. + vm.expectRevert("TimelockController: operation is not ready"); + timelockController.execute( + address(timelockControllerHandler), + 0, + abi.encodeWithSelector( + TimelockControllerHandler.increment.selector + ), + bytes32(""), + bytes32(cancelled[i]) + ); + } + } + + // Executing a proposal that is not ready is not possible + function invariantExecutingNotReadyProposal() public { + uint256[] memory pending = timelockControllerHandler.getPending(); + // Loop over all pending proposals. + for (uint256 i = 0; i < pending.length; ++i) { + // Check that the pending proposal cannot be executed. + vm.expectRevert("TimelockController: operation is not ready"); + timelockController.execute( + address(timelockControllerHandler), + 0, + abi.encodeWithSelector( + TimelockControllerHandler.increment.selector + ), + bytes32(""), + bytes32(pending[i]) + ); + } + } } -// contract TimelockControllerInvariants is Test { -// VyperDeployer private vyperDeployer = new VyperDeployer(); - -// ITimelockController private timelockController; -// TimelockControllerHandler private timelockControllerHandler; - -// function setUp() public { -// address[] memory proposers = new address[](1); -// proposers[0] = address(this); - -// address[] memory executors = new address[](1); -// executors[0] = address(this); - -// uint256 minDelay = 2 days; - -// bytes memory args = abi.encode( -// minDelay, -// proposers, -// executors, -// address(this) -// ); -// timelockController = ITimelockController( -// payable( -// vyperDeployer.deployContract( -// "src/governance/", -// "TimelockController", -// args -// ) -// ) -// ); - -// timelockControllerHandler = new TimelockControllerHandler( -// timelockController, -// minDelay, -// proposers, -// executors, -// address(this) -// ); - -// // Select the selectors to use for fuzzing. -// bytes4[] memory selectors = new bytes4[](3); -// selectors[0] = TimelockControllerHandler.schedule.selector; -// selectors[1] = TimelockControllerHandler.execute.selector; -// selectors[2] = TimelockControllerHandler.cancel.selector; - -// // Set the target selector. -// targetSelector( -// FuzzSelector({ -// addr: address(timelockControllerHandler), -// selectors: selectors -// }) -// ); - -// // Set the target contract. -// targetContract(address(timelockControllerHandler)); -// } - -// // Number of pending transactions cannot exceed executed transactions -// function invariantExecutedLessThanOrEqualToPending() public { -// assertLe( -// timelockControllerHandler.execute_count(), -// timelockControllerHandler.schedule_count() -// ); -// } - -// // Number of proposals executed must match the count number. -// function invariantProposalsExecutedMatchCount() public { -// assertEq( -// timelockControllerHandler.execute_count(), -// timelockControllerHandler.counter() -// ); -// } - -// // Proposals can only be scheduled and executed once -// function invariantOnceProposalExecution() public { -// uint256[] memory executed = timelockControllerHandler.getExecuted(); -// // Loop over all executed proposals. -// for (uint256 i = 0; i < executed.length; ++i) { -// // Check that the executed proposal cannot be executed again. -// vm.expectRevert("TimelockController: operation is not ready"); -// timelockController.execute( -// address(timelockControllerHandler), -// 0, -// abi.encodeWithSelector( -// TimelockControllerHandler.increment.selector -// ), -// bytes32(""), -// bytes32(executed[i]) -// ); -// } -// } - -// // Sum of number of executed proposals and cancelled proposals must be less or equal to the amount of proposals scheduled. -// function invariantSumOfProposals() public { -// assertLe( -// timelockControllerHandler.cancel_count() + -// timelockControllerHandler.execute_count(), -// timelockControllerHandler.schedule_count() -// ); -// } - -// // Executed proposals cannot be cancelled -// function invariantExecutedProposalCancellation() public { -// uint256[] memory executed = timelockControllerHandler.getExecuted(); -// // Loop over all executed proposals. -// for (uint256 i = 0; i < executed.length; ++i) { -// // Check that the executed proposal cannot be cancelled. -// vm.expectRevert( -// "TimelockController: operation cannot be cancelled" -// ); -// timelockController.cancel(bytes32(executed[i])); -// } -// } - -// // Executing a proposal that has been cancelled is not possible -// function invariantExecutingCancelledProposal() public { -// uint256[] memory cancelled = timelockControllerHandler.getCancelled(); -// // Loop over all cancelled proposals. -// for (uint256 i = 0; i < cancelled.length; ++i) { -// // Check that the cancelled proposal cannot be executed. -// vm.expectRevert("TimelockController: operation is not ready"); -// timelockController.execute( -// address(timelockControllerHandler), -// 0, -// abi.encodeWithSelector( -// TimelockControllerHandler.increment.selector -// ), -// bytes32(""), -// bytes32(cancelled[i]) -// ); -// } -// } - -// // Executing a proposal that is not ready is not possible -// function invariantExecutingNotReadyProposal() public { -// uint256[] memory pending = timelockControllerHandler.getPending(); -// // Loop over all pending proposals. -// for (uint256 i = 0; i < pending.length; ++i) { -// // Check that the pending proposal cannot be executed. -// vm.expectRevert("TimelockController: operation is not ready"); -// timelockController.execute( -// address(timelockControllerHandler), -// 0, -// abi.encodeWithSelector( -// TimelockControllerHandler.increment.selector -// ), -// bytes32(""), -// bytes32(pending[i]) -// ); -// } -// } -// } - -// contract TimelockControllerHandler is Test { -// ITimelockController private timelockController; -// uint256 private minDelay; -// address private admin; -// address private proposer; -// address private executor; - -// uint256 public counter; - -// uint256 public schedule_count; -// uint256 public execute_count; -// uint256 public cancel_count; - -// uint256[] public pending; -// uint256[] public executed; -// uint256[] public cancelled; - -// constructor( -// ITimelockController timelockController_, -// uint256 minDelay_, -// address[] memory proposer_, -// address[] memory executor_, -// address admin_ -// ) { -// timelockController = timelockController_; -// minDelay = minDelay_; -// proposer = proposer_[0]; -// executor = executor_[0]; -// admin = admin_; -// } - -// function schedule(uint256 random) external { -// vm.prank(proposer); -// timelockController.schedule( -// address(this), -// 0, -// abi.encodeWithSelector(this.increment.selector), -// bytes32(""), -// bytes32(random), -// minDelay -// ); - -// pending.push(random); -// schedule_count++; -// } - -// function execute(uint256 random) external { -// if (pending.length == 0 || schedule_count == 0) { -// return; -// } - -// uint256 identifier = random % pending.length; -// uint256 operation = pending[identifier]; - -// // Advance time to make the proposal ready. -// vm.warp(block.timestamp + minDelay); - -// vm.prank(executor); -// timelockController.execute( -// address(this), -// 0, -// abi.encodeWithSelector(this.increment.selector), -// bytes32(""), -// bytes32(operation) -// ); - -// delete pending[identifier]; -// executed.push(operation); - -// execute_count++; -// } - -// function cancel(uint256 random) external { -// if (pending.length == 0 || schedule_count == 0) { -// return; -// } - -// uint256 identifier = random % pending.length; -// uint256 operation = pending[identifier]; - -// vm.prank(proposer); -// timelockController.cancel(bytes32(operation)); - -// delete pending[identifier]; -// cancelled.push(operation); - -// cancel_count++; -// } - -// function getExecuted() external view returns (uint256[] memory) { -// return executed; -// } - -// function getCancelled() external view returns (uint256[] memory) { -// return cancelled; -// } - -// function getPending() external view returns (uint256[] memory) { -// return pending; -// } - -// function increment() external { -// counter++; -// } -// } +contract TimelockControllerHandler is Test { + ITimelockController private timelockController; + uint256 private minDelay; + address private admin; + address private proposer; + address private executor; + + uint256 public counter; + + uint256 public schedule_count; + uint256 public execute_count; + uint256 public cancel_count; + + uint256[] public pending; + uint256[] public executed; + uint256[] public cancelled; + + constructor( + ITimelockController timelockController_, + uint256 minDelay_, + address[] memory proposer_, + address[] memory executor_, + address admin_ + ) { + timelockController = timelockController_; + minDelay = minDelay_; + proposer = proposer_[0]; + executor = executor_[0]; + admin = admin_; + } + + function schedule(uint256 random) external { + vm.prank(proposer); + timelockController.schedule( + address(this), + 0, + abi.encodeWithSelector(this.increment.selector), + bytes32(""), + bytes32(random), + minDelay + ); + + pending.push(random); + schedule_count++; + } + + function execute(uint256 random) external { + if (pending.length == 0 || schedule_count == 0) { + return; + } + + uint256 identifier = random % pending.length; + uint256 operation = pending[identifier]; + + // Advance time to make the proposal ready. + vm.warp(block.timestamp + minDelay); + + vm.prank(executor); + timelockController.execute( + address(this), + 0, + abi.encodeWithSelector(this.increment.selector), + bytes32(""), + bytes32(operation) + ); + + delete pending[identifier]; + executed.push(operation); + + execute_count++; + } + + function cancel(uint256 random) external { + if (pending.length == 0 || schedule_count == 0) { + return; + } + + uint256 identifier = random % pending.length; + uint256 operation = pending[identifier]; + + vm.prank(proposer); + timelockController.cancel(bytes32(operation)); + + delete pending[identifier]; + cancelled.push(operation); + + cancel_count++; + } + + function getExecuted() external view returns (uint256[] memory) { + return executed; + } + + function getCancelled() external view returns (uint256[] memory) { + return cancelled; + } + + function getPending() external view returns (uint256[] memory) { + return pending; + } + + function increment() external { + counter++; + } +} diff --git a/test/governance/mocks/CallReceiverMock.sol b/test/governance/mocks/CallReceiverMock.sol index d824bcbf..014e6f5f 100644 --- a/test/governance/mocks/CallReceiverMock.sol +++ b/test/governance/mocks/CallReceiverMock.sol @@ -93,7 +93,7 @@ contract CallReceiverMock { function mockFunctionWritesStorage( bytes32 slot, bytes32 value - ) public returns (string memory) { + ) public payable returns (string memory) { // solhint-disable-next-line no-inline-assembly assembly { sstore(slot, value) From 0abe91237b7f444ea98318b36939b5f672cfbde3 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Wed, 31 Jan 2024 13:19:17 +0100 Subject: [PATCH 43/46] =?UTF-8?q?=F0=9F=93=96=20chore=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/governance/TimelockController.t.sol | 38 ++++++++++++------- .../interfaces/ITimelockController.sol | 4 +- test/governance/mocks/CallReceiverMock.sol | 1 - 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index 7f670316..c2cc4cca 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -16,6 +16,12 @@ import {IERC721Extended} from "../tokens/interfaces/IERC721Extended.sol"; import {IERC1155Extended} from "../tokens/interfaces/IERC1155Extended.sol"; import {ITimelockController} from "./interfaces/ITimelockController.sol"; +/** + * @dev The standard access control functionalities are not tested as they + * were taken 1:1 from `AccessControl.vy`. See `AccessControl.t.sol` for the + * corresponding tests. However, please integrate these tests into your own + * test suite before deploying `TimelockController` into production! + */ contract TimelockControllerTest is Test { bytes32 private constant DEFAULT_ADMIN_ROLE = bytes32(0); bytes32 private constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); @@ -3722,9 +3728,10 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); - assertEq(timelockController.get_timestamp( - batchedOperationId - ), DONE_TIMESTAMP); + assertEq( + timelockController.get_timestamp(batchedOperationId), + DONE_TIMESTAMP + ); assertEq(erc721Mock.balanceOf(timelockControllerAddr), 0); } @@ -3743,7 +3750,12 @@ contract TimelockControllerTest is Test { vm.startPrank(deployer); erc1155Mock.safe_mint(timelockControllerAddr, 0, 1, new bytes(0)); - erc1155Mock.safe_mint_batch(timelockControllerAddr, ids, tokenAmounts, new bytes(0)); + erc1155Mock.safe_mint_batch( + timelockControllerAddr, + ids, + tokenAmounts, + new bytes(0) + ); assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 0), 1); assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 1), 1); assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 2), 2); @@ -3811,9 +3823,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - assertEq(timelockController.get_timestamp( - batchedOperationId - ), DONE_TIMESTAMP); + assertEq( + timelockController.get_timestamp(batchedOperationId), + DONE_TIMESTAMP + ); assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 0), 0); } @@ -3872,9 +3885,7 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); - assertEq(timelockController.get_timestamp( - operationId - ), DONE_TIMESTAMP); + assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); assertEq(address(callReceiverMock).balance, amount); } @@ -3943,9 +3954,10 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); - assertEq(timelockController.get_timestamp( - batchedOperationId - ), DONE_TIMESTAMP); + assertEq( + timelockController.get_timestamp(batchedOperationId), + DONE_TIMESTAMP + ); assertEq(address(callReceiverMock).balance, amounts[0]); } } diff --git a/test/governance/interfaces/ITimelockController.sol b/test/governance/interfaces/ITimelockController.sol index cfd7ac39..da07566b 100644 --- a/test/governance/interfaces/ITimelockController.sol +++ b/test/governance/interfaces/ITimelockController.sol @@ -67,8 +67,8 @@ interface ITimelockController is function is_operation_done(bytes32 id) external view returns (bool); /** - * @dev As Enums are handled differently in Vyper and Solidity, we return - * the directly underlying Vyper type `uint256` (instead of `OperationState`) + * @dev As Enums are handled differently in Vyper and Solidity (see https://twitter.com/pcaversaccio/status/1626514029094047747), + * we directly return the underlying Vyper type `uint256` (instead of `OperationState`) * for Enums for ease of testing. */ function get_operation_state(bytes32 id) external view returns (uint256); diff --git a/test/governance/mocks/CallReceiverMock.sol b/test/governance/mocks/CallReceiverMock.sol index 014e6f5f..c6be49e3 100644 --- a/test/governance/mocks/CallReceiverMock.sol +++ b/test/governance/mocks/CallReceiverMock.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.23; /** * @title CallReceiverMock * @author pcaversaccio - * @custom:coauthor cairoeth * @notice Forked and adjusted accordingly from here: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/CallReceiverMock.sol. * @dev Allows to test receiving state-changing and/or static external calls. From b7988e85f0c6732284d9bce3369103e42cf1703e Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Thu, 1 Feb 2024 13:58:57 +0100 Subject: [PATCH 44/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20Add=20Further=20T?= =?UTF-8?q?ests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- .solhint.json | 3 +- test/governance/TimelockController.t.sol | 312 ++++++++++++++++++++--- 2 files changed, 277 insertions(+), 38 deletions(-) diff --git a/.solhint.json b/.solhint.json index 127600a2..aeadcf84 100644 --- a/.solhint.json +++ b/.solhint.json @@ -4,6 +4,7 @@ "func-visibility": ["warn", { "ignoreConstructors": true }], "func-name-mixedcase": "off", "private-vars-leading-underscore": "off", - "one-contract-per-file": "off" + "one-contract-per-file": "off", + "max-states-count": "off" } } diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index c2cc4cca..a00caf8f 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -85,9 +85,10 @@ contract TimelockControllerTest is Test { bytes32 role, address[2] storage addresses ) internal { - for (uint256 i = 0; i < addresses.length; ++i) { - assertTrue(!accessControl.hasRole(role, addresses[i])); - } + assertTrue( + !accessControl.hasRole(role, addresses[0]) && + !accessControl.hasRole(role, addresses[1]) + ); } function setUp() public { @@ -994,6 +995,62 @@ contract TimelockControllerTest is Test { vm.stopPrank(); } + function testCompletePipelineOperationMinimumDelayUpdate() public { + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + timelockController.update_delay.selector, + MIN_DELAY + 31 days + ); + bytes32 operationId = timelockController.hash_operation( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + timelockControllerAddr, + amount, + payload + ); + timelockController.execute( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(timelockController.get_minimum_delay(), MIN_DELAY + 31 days); + vm.stopPrank(); + } + function testOperationOperationIsNotReady() public { uint256 amount = 0; bytes memory payload = new bytes(0); @@ -2066,6 +2123,7 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); + vm.startPrank(PROPOSER_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(true, true, false, true); @@ -3247,8 +3305,7 @@ contract TimelockControllerTest is Test { ); timelockController.update_delay(newMinDelay); vm.stopPrank(); - uint256 minDelay = timelockController.get_minimum_delay(); - assertEq(minDelay, newMinDelay); + assertEq(timelockController.get_minimum_delay(), newMinDelay); } function testInvalidOperation() public { @@ -3261,7 +3318,7 @@ contract TimelockControllerTest is Test { timelockController.update_delay(3 days); } - function testAdminCantBatchSchedule() public { + function testAdminCannotBatchSchedule() public { address[] memory targets = new address[](0); uint256[] memory amounts = new uint256[](0); bytes[] memory payloads = new bytes[](0); @@ -3277,7 +3334,7 @@ contract TimelockControllerTest is Test { ); } - function testAdminCantSchedule() public { + function testAdminCannotSchedule() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(self); timelockController.schedule( @@ -3290,7 +3347,7 @@ contract TimelockControllerTest is Test { ); } - function testAdminCantBatchExecute() public { + function testAdminCannotBatchExecute() public { address[] memory targets = new address[](0); uint256[] memory amounts = new uint256[](0); bytes[] memory payloads = new bytes[](0); @@ -3306,7 +3363,7 @@ contract TimelockControllerTest is Test { ); } - function testAdminCantExecute() public { + function testAdminCannotExecute() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(self); timelockController.execute( @@ -3318,7 +3375,7 @@ contract TimelockControllerTest is Test { ); } - function testAdminCantCancel() public { + function testAdminCannotCancel() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(self); timelockController.cancel(EMPTY_SALT); @@ -3369,13 +3426,13 @@ contract TimelockControllerTest is Test { 0, new bytes(0), NO_PREDECESSOR, - bytes32("1"), + SALT, MIN_DELAY ); vm.stopPrank(); } - function testProposerCantBatchExecute() public { + function testProposerCannotBatchExecute() public { address[] memory targets = new address[](0); uint256[] memory amounts = new uint256[](0); bytes[] memory payloads = new bytes[](0); @@ -3397,11 +3454,11 @@ contract TimelockControllerTest is Test { amounts, payloads, NO_PREDECESSOR, - bytes32("1") + SALT ); } - function testProposerCantExecute() public { + function testProposerCannotExecute() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(PROPOSER_ONE); timelockController.execute( @@ -3419,7 +3476,7 @@ contract TimelockControllerTest is Test { 0, new bytes(0), NO_PREDECESSOR, - bytes32("1") + SALT ); } @@ -3433,7 +3490,7 @@ contract TimelockControllerTest is Test { timelockController.cancel(EMPTY_SALT); } - function testExecutorCantBatchSchedule() public { + function testExecutorCannotBatchSchedule() public { address[] memory targets = new address[](0); uint256[] memory amounts = new uint256[](0); bytes[] memory payloads = new bytes[](0); @@ -3456,12 +3513,12 @@ contract TimelockControllerTest is Test { amounts, payloads, NO_PREDECESSOR, - bytes32("1"), + SALT, MIN_DELAY ); } - function testExecutorCantSchedule() public { + function testExecutorCannotSchedule() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(EXECUTOR_ONE); timelockController.schedule( @@ -3480,7 +3537,7 @@ contract TimelockControllerTest is Test { 0, new bytes(0), NO_PREDECESSOR, - bytes32("1"), + SALT, MIN_DELAY ); } @@ -3507,7 +3564,7 @@ contract TimelockControllerTest is Test { amounts, payloads, NO_PREDECESSOR, - bytes32("1") + SALT ); } @@ -3529,11 +3586,11 @@ contract TimelockControllerTest is Test { 0, new bytes(0), NO_PREDECESSOR, - bytes32("1") + SALT ); } - function testExecutorCantCancel() public { + function testExecutorCannotCancel() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(EXECUTOR_ONE); timelockController.cancel(EMPTY_SALT); @@ -3543,7 +3600,7 @@ contract TimelockControllerTest is Test { timelockController.cancel(EMPTY_SALT); } - function testStrangerCantBatchSchedule() public { + function testStrangerCannotBatchSchedule() public { address[] memory targets = new address[](0); uint256[] memory amounts = new uint256[](0); bytes[] memory payloads = new bytes[](0); @@ -3560,7 +3617,7 @@ contract TimelockControllerTest is Test { ); } - function testStrangerCantSchedule() public { + function testStrangerCannotSchedule() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); timelockController.schedule( @@ -3573,7 +3630,7 @@ contract TimelockControllerTest is Test { ); } - function testStrangerCantBatchExecute() public { + function testStrangerCannotBatchExecute() public { address[] memory targets = new address[](0); uint256[] memory amounts = new uint256[](0); bytes[] memory payloads = new bytes[](0); @@ -3589,7 +3646,7 @@ contract TimelockControllerTest is Test { ); } - function testStrangerCantExecute() public { + function testStrangerCannotExecute() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); timelockController.execute( @@ -3601,7 +3658,7 @@ contract TimelockControllerTest is Test { ); } - function testStrangerCantCancel() public { + function testStrangerCannotCancel() public { vm.expectRevert("AccessControl: account is missing role"); vm.prank(STRANGER); timelockController.cancel(EMPTY_SALT); @@ -3656,6 +3713,142 @@ contract TimelockControllerTest is Test { vm.stopPrank(); } + function testCompletePipelineOperationSetRoleAdmin() public { + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + timelockController.set_role_admin.selector, + EXECUTOR_ROLE, + PROPOSER_ROLE + ); + bytes32 operationId = timelockController.hash_operation( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(EXECUTOR_ONE); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleAdminChanged( + EXECUTOR_ROLE, + DEFAULT_ADMIN_ROLE, + PROPOSER_ROLE + ); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + timelockControllerAddr, + amount, + payload + ); + timelockController.execute( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(timelockController.getRoleAdmin(EXECUTOR_ROLE), PROPOSER_ROLE); + assertTrue( + timelockController.getRoleAdmin(EXECUTOR_ROLE) != DEFAULT_ADMIN_ROLE + ); + vm.stopPrank(); + } + + function testCompleteOperationWithAssignExecutorRoleToZeroAddress() public { + vm.startPrank(timelockControllerAddr); + timelockController.grantRole(EXECUTOR_ROLE, zeroAddress); + vm.stopPrank(); + + uint256 amount = 0; + bytes memory payload = abi.encodeWithSelector( + timelockController.set_role_admin.selector, + EXECUTOR_ROLE, + PROPOSER_ROLE + ); + bytes32 operationId = timelockController.hash_operation( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + + vm.startPrank(PROPOSER_ONE); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallScheduled( + operationId, + 0, + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + MIN_DELAY + ); + timelockController.schedule( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT, + MIN_DELAY + ); + vm.stopPrank(); + + vm.warp(block.timestamp + MIN_DELAY); + vm.startPrank(STRANGER); + vm.expectEmit(true, true, true, false); + emit IAccessControl.RoleAdminChanged( + EXECUTOR_ROLE, + DEFAULT_ADMIN_ROLE, + PROPOSER_ROLE + ); + vm.expectEmit(true, true, false, true); + emit ITimelockController.CallExecuted( + operationId, + 0, + timelockControllerAddr, + amount, + payload + ); + timelockController.execute( + timelockControllerAddr, + amount, + payload, + NO_PREDECESSOR, + EMPTY_SALT + ); + assertEq(timelockController.getRoleAdmin(EXECUTOR_ROLE), PROPOSER_ROLE); + assertTrue( + timelockController.getRoleAdmin(EXECUTOR_ROLE) != DEFAULT_ADMIN_ROLE + ); + vm.stopPrank(); + } + function testHandleERC721() public { bytes memory args = abi.encode( "MyNFT", @@ -3733,6 +3926,7 @@ contract TimelockControllerTest is Test { DONE_TIMESTAMP ); assertEq(erc721Mock.balanceOf(timelockControllerAddr), 0); + vm.stopPrank(); } function testHandleERC1155() public { @@ -3740,7 +3934,6 @@ contract TimelockControllerTest is Test { erc1155Mock = IERC1155Extended( vyperDeployer.deployContract("src/tokens/", "ERC1155", args) ); - uint256[] memory ids = new uint256[](2); uint256[] memory tokenAmounts = new uint256[](2); ids[0] = 1; @@ -3780,7 +3973,7 @@ contract TimelockControllerTest is Test { EMPTY_SALT ); - vm.prank(PROPOSER_ONE); + vm.startPrank(PROPOSER_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(true, true, false, true); emit ITimelockController.CallScheduled( @@ -3801,10 +3994,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); + vm.stopPrank(); vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); + vm.startPrank(EXECUTOR_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(true, true, false, true); emit ITimelockController.CallExecuted( @@ -3822,12 +4015,32 @@ contract TimelockControllerTest is Test { NO_PREDECESSOR, EMPTY_SALT ); - assertEq( timelockController.get_timestamp(batchedOperationId), DONE_TIMESTAMP ); assertEq(erc1155Mock.balanceOf(timelockControllerAddr, 0), 0); + vm.stopPrank(); + } + + function testFuzzHashOperation( + address target_, + uint256 amount, + bytes memory payload, + bytes32 predecessor, + bytes32 salt + ) public { + bytes32 operationId = timelockController.hash_operation( + target_, + amount, + payload, + predecessor, + salt + ); + assertEq( + operationId, + keccak256(abi.encode(target_, amount, payload, predecessor, salt)) + ); } function testFuzzOperationValue(uint256 amount) public { @@ -3848,7 +4061,7 @@ contract TimelockControllerTest is Test { ); deal(timelockControllerAddr, amount); - vm.prank(PROPOSER_ONE); + vm.startPrank(PROPOSER_ONE); vm.expectEmit(true, true, false, true); emit ITimelockController.CallScheduled( operationId, @@ -3867,9 +4080,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); + vm.stopPrank(); vm.warp(block.timestamp + MIN_DELAY); - vm.prank(EXECUTOR_ONE); + vm.startPrank(EXECUTOR_ONE); vm.expectEmit(true, true, false, true); emit ITimelockController.CallExecuted( operationId, @@ -3887,6 +4101,29 @@ contract TimelockControllerTest is Test { ); assertEq(timelockController.get_timestamp(operationId), DONE_TIMESTAMP); assertEq(address(callReceiverMock).balance, amount); + vm.stopPrank(); + } + + function testFuzzHashOperationBatch( + address[] memory targets_, + uint256[] memory amounts, + bytes[] memory payloads, + bytes32 predecessor, + bytes32 salt + ) public { + bytes32 batchedOperationId = timelockController.hash_operation_batch( + targets_, + amounts, + payloads, + predecessor, + salt + ); + assertEq( + batchedOperationId, + keccak256( + abi.encode(targets_, amounts, payloads, predecessor, salt) + ) + ); } function testFuzzBatchValue(uint256 amount) public { @@ -3912,7 +4149,7 @@ contract TimelockControllerTest is Test { ); deal(timelockControllerAddr, amount); - vm.prank(PROPOSER_ONE); + vm.startPrank(PROPOSER_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(true, true, false, true); emit ITimelockController.CallScheduled( @@ -3933,10 +4170,10 @@ contract TimelockControllerTest is Test { EMPTY_SALT, MIN_DELAY ); + vm.stopPrank(); vm.warp(block.timestamp + MIN_DELAY); - - vm.prank(EXECUTOR_ONE); + vm.startPrank(EXECUTOR_ONE); for (uint256 i = 0; i < targets.length; ++i) { vm.expectEmit(true, true, false, true); emit ITimelockController.CallExecuted( @@ -3959,6 +4196,7 @@ contract TimelockControllerTest is Test { DONE_TIMESTAMP ); assertEq(address(callReceiverMock).balance, amounts[0]); + vm.stopPrank(); } } From b744bce7c3ac525ba2d5bcc08231c3a88b36192f Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Thu, 1 Feb 2024 16:02:43 +0100 Subject: [PATCH 45/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20small=20chore=20r?= =?UTF-8?q?efactor=20invariant=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- test/governance/TimelockController.t.sol | 156 +++++++++++------------ 1 file changed, 75 insertions(+), 81 deletions(-) diff --git a/test/governance/TimelockController.t.sol b/test/governance/TimelockController.t.sol index a00caf8f..21ab477e 100644 --- a/test/governance/TimelockController.t.sol +++ b/test/governance/TimelockController.t.sol @@ -4206,82 +4206,73 @@ contract TimelockControllerInvariants is Test { ITimelockController private timelockController; TimelockControllerHandler private timelockControllerHandler; + address private self = address(this); + address private timelockControllerAddr; + function setUp() public { address[] memory proposers = new address[](1); - proposers[0] = address(this); - + proposers[0] = self; address[] memory executors = new address[](1); - executors[0] = address(this); - + executors[0] = self; uint256 minDelay = 2 days; - - bytes memory args = abi.encode( - minDelay, - proposers, - executors, - address(this) - ); + bytes memory args = abi.encode(minDelay, proposers, executors, self); timelockController = ITimelockController( - payable( - vyperDeployer.deployContract( - "src/governance/", - "TimelockController", - args - ) + vyperDeployer.deployContract( + "src/governance/", + "TimelockController", + args ) ); - timelockControllerHandler = new TimelockControllerHandler( timelockController, minDelay, proposers, executors, - address(this) + self ); + timelockControllerAddr = address(timelockControllerHandler); - // Select the selectors to use for fuzzing. bytes4[] memory selectors = new bytes4[](3); selectors[0] = TimelockControllerHandler.schedule.selector; selectors[1] = TimelockControllerHandler.execute.selector; selectors[2] = TimelockControllerHandler.cancel.selector; - - // Set the target selector. targetSelector( - FuzzSelector({ - addr: address(timelockControllerHandler), - selectors: selectors - }) + FuzzSelector({addr: timelockControllerAddr, selectors: selectors}) ); - - // Set the target contract. - targetContract(address(timelockControllerHandler)); + targetContract(timelockControllerAddr); } - // Number of pending transactions cannot exceed executed transactions - function invariantExecutedLessThanOrEqualToPending() public { - assertLe( - timelockControllerHandler.execute_count(), - timelockControllerHandler.schedule_count() + /** + * @dev The number of scheduled transactions cannot exceed the number of + * executed transactions. + */ + function invariantExecutedLessThanOrEqualToScheduled() public { + assertTrue( + timelockControllerHandler.executeCount() <= + timelockControllerHandler.scheduleCount() ); } - // Number of proposals executed must match the count number. + /** + * @dev The number of proposals executed must match the count number. + */ function invariantProposalsExecutedMatchCount() public { assertEq( - timelockControllerHandler.execute_count(), + timelockControllerHandler.executeCount(), timelockControllerHandler.counter() ); } - // Proposals can only be scheduled and executed once + /** + * @dev Proposals can only be scheduled and executed once. + */ function invariantOnceProposalExecution() public { uint256[] memory executed = timelockControllerHandler.getExecuted(); - // Loop over all executed proposals. for (uint256 i = 0; i < executed.length; ++i) { - // Check that the executed proposal cannot be executed again. + // Ensure that the executed proposal cannot be executed again. vm.expectRevert("TimelockController: operation is not ready"); timelockController.execute( - address(timelockControllerHandler), + timelockControllerAddr, 0, abi.encodeWithSelector( TimelockControllerHandler.increment.selector @@ -4292,21 +4283,25 @@ contract TimelockControllerInvariants is Test { } } - // Sum of number of executed proposals and cancelled proposals must be less or equal to the amount of proposals scheduled. + /** + * @dev The sum of the executed proposals and the cancelled proposals must + * be less than or equal to the number of scheduled proposals. + */ function invariantSumOfProposals() public { - assertLe( - timelockControllerHandler.cancel_count() + - timelockControllerHandler.execute_count(), - timelockControllerHandler.schedule_count() + assertTrue( + (timelockControllerHandler.cancelCount() + + timelockControllerHandler.executeCount()) <= + timelockControllerHandler.scheduleCount() ); } - // Executed proposals cannot be cancelled + /** + * @dev The executed proposals cannot be cancelled. + */ function invariantExecutedProposalCancellation() public { uint256[] memory executed = timelockControllerHandler.getExecuted(); - // Loop over all executed proposals. for (uint256 i = 0; i < executed.length; ++i) { - // Check that the executed proposal cannot be cancelled. + // Ensure that the executed proposal cannot be cancelled. vm.expectRevert( "TimelockController: operation cannot be cancelled" ); @@ -4314,12 +4309,13 @@ contract TimelockControllerInvariants is Test { } } - // Executing a proposal that has been cancelled is not possible + /** + * @dev The execution of a proposal that has been cancelled is not possible. + */ function invariantExecutingCancelledProposal() public { uint256[] memory cancelled = timelockControllerHandler.getCancelled(); - // Loop over all cancelled proposals. for (uint256 i = 0; i < cancelled.length; ++i) { - // Check that the cancelled proposal cannot be executed. + // Ensure that the cancelled proposal cannot be executed. vm.expectRevert("TimelockController: operation is not ready"); timelockController.execute( address(timelockControllerHandler), @@ -4333,12 +4329,13 @@ contract TimelockControllerInvariants is Test { } } - // Executing a proposal that is not ready is not possible + /** + * @dev The execution of a proposal that is not ready is not possible. + */ function invariantExecutingNotReadyProposal() public { uint256[] memory pending = timelockControllerHandler.getPending(); - // Loop over all pending proposals. for (uint256 i = 0; i < pending.length; ++i) { - // Check that the pending proposal cannot be executed. + // Ensure that the pending proposal cannot be executed. vm.expectRevert("TimelockController: operation is not ready"); timelockController.execute( address(timelockControllerHandler), @@ -4354,21 +4351,21 @@ contract TimelockControllerInvariants is Test { } contract TimelockControllerHandler is Test { + uint256 public counter; + uint256 public scheduleCount; + uint256 public executeCount; + uint256 public cancelCount; + ITimelockController private timelockController; + + address private self = address(this); uint256 private minDelay; address private admin; address private proposer; address private executor; - - uint256 public counter; - - uint256 public schedule_count; - uint256 public execute_count; - uint256 public cancel_count; - - uint256[] public pending; - uint256[] public executed; - uint256[] public cancelled; + uint256[] private pending; + uint256[] private executed; + uint256[] private cancelled; constructor( ITimelockController timelockController_, @@ -4385,61 +4382,58 @@ contract TimelockControllerHandler is Test { } function schedule(uint256 random) external { - vm.prank(proposer); + vm.startPrank(proposer); timelockController.schedule( - address(this), + self, 0, abi.encodeWithSelector(this.increment.selector), bytes32(""), bytes32(random), minDelay ); - pending.push(random); - schedule_count++; + scheduleCount++; + vm.stopPrank(); } function execute(uint256 random) external { - if (pending.length == 0 || schedule_count == 0) { + if (pending.length == 0 || scheduleCount == 0) { return; } uint256 identifier = random % pending.length; uint256 operation = pending[identifier]; - // Advance time to make the proposal ready. + // Advance the time to make the proposal ready. vm.warp(block.timestamp + minDelay); - - vm.prank(executor); + vm.startPrank(executor); timelockController.execute( - address(this), + self, 0, abi.encodeWithSelector(this.increment.selector), bytes32(""), bytes32(operation) ); - delete pending[identifier]; executed.push(operation); - - execute_count++; + executeCount++; + vm.stopPrank(); } function cancel(uint256 random) external { - if (pending.length == 0 || schedule_count == 0) { + if (pending.length == 0 || scheduleCount == 0) { return; } uint256 identifier = random % pending.length; uint256 operation = pending[identifier]; - vm.prank(proposer); + vm.startPrank(proposer); timelockController.cancel(bytes32(operation)); - delete pending[identifier]; cancelled.push(operation); - - cancel_count++; + cancelCount++; + vm.stopPrank(); } function getExecuted() external view returns (uint256[] memory) { From defbfd5d82707598775d85f891f643fe3b2417e4 Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Thu, 1 Feb 2024 16:12:09 +0100 Subject: [PATCH 46/46] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20Add=20`.gas-snaps?= =?UTF-8?q?hot`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pascal Marco Caversaccio --- .gas-snapshot | 318 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 205 insertions(+), 113 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 9f91dc85..994774a5 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -4,12 +4,12 @@ AccessControlTest:testFuzzGrantRoleAdminRoleSuccess(address) (runs: 256, μ: 437 AccessControlTest:testFuzzGrantRoleMultipleTimesSuccess(address) (runs: 256, μ: 48930, ~: 48930) AccessControlTest:testFuzzGrantRoleNonAdmin(address,address) (runs: 256, μ: 16544, ~: 16544) AccessControlTest:testFuzzGrantRoleSuccess(address) (runs: 256, μ: 43797, ~: 43797) -AccessControlTest:testFuzzRenounceRoleMultipleTimesSuccess(address) (runs: 256, μ: 44372, ~: 44356) +AccessControlTest:testFuzzRenounceRoleMultipleTimesSuccess(address) (runs: 256, μ: 44371, ~: 44356) AccessControlTest:testFuzzRenounceRoleNonMsgSender(address) (runs: 256, μ: 9556, ~: 9556) -AccessControlTest:testFuzzRenounceRoleSuccess(address) (runs: 256, μ: 40867, ~: 40851) -AccessControlTest:testFuzzRevokeRoleMultipleTimesSuccess(address) (runs: 256, μ: 40637, ~: 40620) +AccessControlTest:testFuzzRenounceRoleSuccess(address) (runs: 256, μ: 40866, ~: 40851) +AccessControlTest:testFuzzRevokeRoleMultipleTimesSuccess(address) (runs: 256, μ: 40636, ~: 40620) AccessControlTest:testFuzzRevokeRoleNonAdmin(address,address) (runs: 256, μ: 16498, ~: 16498) -AccessControlTest:testFuzzRevokeRoleSuccess(address) (runs: 256, μ: 39481, ~: 39464) +AccessControlTest:testFuzzRevokeRoleSuccess(address) (runs: 256, μ: 39480, ~: 39464) AccessControlTest:testFuzzSetRoleAdminPreviousAdminCallsGrantRole(address,address) (runs: 256, μ: 75747, ~: 75747) AccessControlTest:testFuzzSetRoleAdminPreviousAdminCallsRevokeRole(address,address) (runs: 256, μ: 101276, ~: 101276) AccessControlTest:testFuzzSetRoleAdminSuccess(address,address) (runs: 256, μ: 89648, ~: 89648) @@ -60,8 +60,8 @@ BatchDistributorTest:testDistributeTokenMultipleAddressesSuccess() (gas: 616202) BatchDistributorTest:testDistributeTokenOneAddressSuccess() (gas: 578527) BatchDistributorTest:testDistributeTokenRevertWithInsufficientAllowance() (gas: 574268) BatchDistributorTest:testDistributeTokenRevertWithInsufficientBalance() (gas: 575054) -BatchDistributorTest:testFuzzDistributeEtherMultipleAddressesSuccess(((address,uint256)[]),uint256) (runs: 256, μ: 1812214, ~: 1793268) -BatchDistributorTest:testFuzzDistributeTokenMultipleAddressesSuccess(((address,uint256)[]),address,uint256) (runs: 256, μ: 1337340, ~: 1321378) +BatchDistributorTest:testFuzzDistributeEtherMultipleAddressesSuccess(((address,uint256)[]),uint256) (runs: 256, μ: 1840920, ~: 1861320) +BatchDistributorTest:testFuzzDistributeTokenMultipleAddressesSuccess(((address,uint256)[]),address,uint256) (runs: 256, μ: 1337465, ~: 1321455) Create2AddressTest:testComputeAddress() (gas: 550599) Create2AddressTest:testComputeAddressSelf() (gas: 558922) Create2AddressTest:testFuzzComputeAddress(bytes32,address) (runs: 256, μ: 551194, ~: 551194) @@ -87,26 +87,26 @@ CreateAddressTest:testComputeAddressSelfNonceUint56() (gas: 539228) CreateAddressTest:testComputeAddressSelfNonceUint64() (gas: 539345) CreateAddressTest:testComputeAddressSelfNonceUint8() (gas: 538951) CreateAddressTest:testComputeAddressSelfRevertTooHighNonce() (gas: 8836) -CreateAddressTest:testFuzzComputeAddressNonce0x7f(uint64,address) (runs: 256, μ: 537963, ~: 538066) -CreateAddressTest:testFuzzComputeAddressNonceUint16(uint64,address) (runs: 256, μ: 537412, ~: 537681) -CreateAddressTest:testFuzzComputeAddressNonceUint24(uint64,address) (runs: 256, μ: 537536, ~: 537657) -CreateAddressTest:testFuzzComputeAddressNonceUint32(uint64,address) (runs: 256, μ: 537551, ~: 537664) -CreateAddressTest:testFuzzComputeAddressNonceUint40(uint64,address) (runs: 256, μ: 537662, ~: 537756) -CreateAddressTest:testFuzzComputeAddressNonceUint48(uint64,address) (runs: 256, μ: 537641, ~: 537740) -CreateAddressTest:testFuzzComputeAddressNonceUint56(uint64,address) (runs: 256, μ: 537687, ~: 537769) -CreateAddressTest:testFuzzComputeAddressNonceUint64(uint64,address) (runs: 256, μ: 537668, ~: 537873) -CreateAddressTest:testFuzzComputeAddressNonceUint8(uint64,address) (runs: 256, μ: 537454, ~: 537531) -CreateAddressTest:testFuzzComputeAddressRevertTooHighNonce(uint256,address) (runs: 256, μ: 12926, ~: 12857) -CreateAddressTest:testFuzzComputeAddressSelfNonce0x7f(uint64) (runs: 256, μ: 543802, ~: 543905) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint16(uint64) (runs: 256, μ: 543016, ~: 542941) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint24(uint64) (runs: 256, μ: 543292, ~: 543395) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint32(uint64) (runs: 256, μ: 543372, ~: 543491) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint40(uint64) (runs: 256, μ: 543390, ~: 543475) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint48(uint64) (runs: 256, μ: 543438, ~: 543549) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint56(uint64) (runs: 256, μ: 543527, ~: 543619) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint64(uint64) (runs: 256, μ: 543599, ~: 543749) -CreateAddressTest:testFuzzComputeAddressSelfNonceUint8(uint64) (runs: 256, μ: 543108, ~: 543186) -CreateAddressTest:testFuzzComputeAddressSelfRevertTooHighNonce(uint256) (runs: 256, μ: 12722, ~: 12696) +CreateAddressTest:testFuzzComputeAddressNonce0x7f(uint64,address) (runs: 256, μ: 537964, ~: 538066) +CreateAddressTest:testFuzzComputeAddressNonceUint16(uint64,address) (runs: 256, μ: 537407, ~: 537680) +CreateAddressTest:testFuzzComputeAddressNonceUint24(uint64,address) (runs: 256, μ: 537539, ~: 537657) +CreateAddressTest:testFuzzComputeAddressNonceUint32(uint64,address) (runs: 256, μ: 537541, ~: 537664) +CreateAddressTest:testFuzzComputeAddressNonceUint40(uint64,address) (runs: 256, μ: 537665, ~: 537756) +CreateAddressTest:testFuzzComputeAddressNonceUint48(uint64,address) (runs: 256, μ: 537642, ~: 537740) +CreateAddressTest:testFuzzComputeAddressNonceUint56(uint64,address) (runs: 256, μ: 537685, ~: 537769) +CreateAddressTest:testFuzzComputeAddressNonceUint64(uint64,address) (runs: 256, μ: 537670, ~: 537873) +CreateAddressTest:testFuzzComputeAddressNonceUint8(uint64,address) (runs: 256, μ: 537453, ~: 537531) +CreateAddressTest:testFuzzComputeAddressRevertTooHighNonce(uint256,address) (runs: 256, μ: 12920, ~: 12857) +CreateAddressTest:testFuzzComputeAddressSelfNonce0x7f(uint64) (runs: 256, μ: 543801, ~: 543905) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint16(uint64) (runs: 256, μ: 543043, ~: 542941) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint24(uint64) (runs: 256, μ: 543302, ~: 543395) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint32(uint64) (runs: 256, μ: 543380, ~: 543491) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint40(uint64) (runs: 256, μ: 543394, ~: 543475) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint48(uint64) (runs: 256, μ: 543437, ~: 543549) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint56(uint64) (runs: 256, μ: 543525, ~: 543619) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint64(uint64) (runs: 256, μ: 543574, ~: 543749) +CreateAddressTest:testFuzzComputeAddressSelfNonceUint8(uint64) (runs: 256, μ: 543109, ~: 543186) +CreateAddressTest:testFuzzComputeAddressSelfRevertTooHighNonce(uint256) (runs: 256, μ: 12735, ~: 12696) ECDSATest:testEthSignedMessageHash() (gas: 5846) ECDSATest:testFuzzEthSignedMessageHash(string) (runs: 256, μ: 6432, ~: 6426) ECDSATest:testFuzzRecoverWithInvalidSignature(bytes,string) (runs: 256, μ: 15159, ~: 15161) @@ -133,7 +133,7 @@ EIP712DomainSeparatorTest:testCachedDomainSeparatorV4() (gas: 7562) EIP712DomainSeparatorTest:testDomainSeparatorV4() (gas: 11305) EIP712DomainSeparatorTest:testEIP712Domain() (gas: 13629) EIP712DomainSeparatorTest:testFuzzDomainSeparatorV4(uint8) (runs: 256, μ: 11460, ~: 11480) -EIP712DomainSeparatorTest:testFuzzEIP712Domain(bytes1,uint8,bytes32,uint256[]) (runs: 256, μ: 19159, ~: 19122) +EIP712DomainSeparatorTest:testFuzzEIP712Domain(bytes1,uint8,bytes32,uint256[]) (runs: 256, μ: 19161, ~: 19122) EIP712DomainSeparatorTest:testFuzzHashTypedDataV4(address,address,uint256,uint256,uint64) (runs: 256, μ: 7698, ~: 7698) EIP712DomainSeparatorTest:testHashTypedDataV4() (gas: 13017) ERC1155Invariants:invariantOwner() (runs: 256, calls: 3840, reverts: 3437) @@ -163,35 +163,35 @@ ERC1155Test:testExistsAfterBatchMint() (gas: 143320) ERC1155Test:testExistsAfterSingleBurn() (gas: 137816) ERC1155Test:testExistsAfterSingleMint() (gas: 119400) ERC1155Test:testExistsBeforeMint() (gas: 7642) -ERC1155Test:testFuzzBurnBatchSuccess(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 132323, ~: 132328) -ERC1155Test:testFuzzBurnSuccess(address,address,uint256) (runs: 256, μ: 140104, ~: 140134) +ERC1155Test:testFuzzBurnBatchSuccess(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 132334, ~: 132343) +ERC1155Test:testFuzzBurnSuccess(address,address,uint256) (runs: 256, μ: 140114, ~: 140134) ERC1155Test:testFuzzRenounceOwnershipNonOwner(address) (runs: 256, μ: 13977, ~: 13977) -ERC1155Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 48433, ~: 48416) -ERC1155Test:testFuzzSafeBatchTransferFromByApprovedOperator(address,address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 225211, ~: 225191) +ERC1155Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 48432, ~: 48416) +ERC1155Test:testFuzzSafeBatchTransferFromByApprovedOperator(address,address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 225230, ~: 225191) ERC1155Test:testFuzzSafeBatchTransferFromEOAReceiver(address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 190347, ~: 190304) -ERC1155Test:testFuzzSafeBatchTransferFromNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 564164, ~: 564164) -ERC1155Test:testFuzzSafeBatchTransferFromWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 564718, ~: 564321) +ERC1155Test:testFuzzSafeBatchTransferFromNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 564154, ~: 564164) +ERC1155Test:testFuzzSafeBatchTransferFromWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 564729, ~: 564321) ERC1155Test:testFuzzSafeMintBatchEOAReceiver(address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 152243, ~: 152222) ERC1155Test:testFuzzSafeMintBatchNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 519951, ~: 519951) ERC1155Test:testFuzzSafeMintBatchNonMinter(address) (runs: 256, μ: 40926, ~: 40926) -ERC1155Test:testFuzzSafeMintBatchWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 520300, ~: 520066) +ERC1155Test:testFuzzSafeMintBatchWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 520295, ~: 520066) ERC1155Test:testFuzzSafeMintEOAReceiver(address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 151294, ~: 151259) ERC1155Test:testFuzzSafeMintNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 520118, ~: 520118) ERC1155Test:testFuzzSafeMintNonMinter(address) (runs: 256, μ: 33132, ~: 33132) ERC1155Test:testFuzzSafeMintWithData(address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 521416, ~: 521009) -ERC1155Test:testFuzzSafeTransferFromByApprovedOperator(address,address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 204219, ~: 204191) +ERC1155Test:testFuzzSafeTransferFromByApprovedOperator(address,address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 204239, ~: 204191) ERC1155Test:testFuzzSafeTransferFromEOAReceiver(address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 169443, ~: 169391) -ERC1155Test:testFuzzSafeTransferFromNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 606373, ~: 606383) -ERC1155Test:testFuzzSafeTransferFromWithData(address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 608365, ~: 607645) +ERC1155Test:testFuzzSafeTransferFromNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 606383, ~: 606383) +ERC1155Test:testFuzzSafeTransferFromWithData(address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 608346, ~: 607645) ERC1155Test:testFuzzSetApprovalForAllRevoke(address,address) (runs: 256, μ: 31053, ~: 31022) ERC1155Test:testFuzzSetApprovalForAllSuccess(address,address) (runs: 256, μ: 44181, ~: 44181) ERC1155Test:testFuzzSetMinterNonOwner(address,string) (runs: 256, μ: 15772, ~: 15699) ERC1155Test:testFuzzSetMinterSuccess(string) (runs: 256, μ: 33178, ~: 33178) ERC1155Test:testFuzzSetUriNonMinter(address) (runs: 256, μ: 14452, ~: 14452) -ERC1155Test:testFuzzTotalSupplyAfterBatchBurn(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 126363, ~: 126368) -ERC1155Test:testFuzzTotalSupplyAfterBatchMint(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 140987, ~: 140922) +ERC1155Test:testFuzzTotalSupplyAfterBatchBurn(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 126374, ~: 126383) +ERC1155Test:testFuzzTotalSupplyAfterBatchMint(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 140991, ~: 141055) ERC1155Test:testFuzzTotalSupplyAfterSingleBurn(address,uint256,bytes) (runs: 256, μ: 138036, ~: 138007) -ERC1155Test:testFuzzTotalSupplyAfterSingleMint(uint256,uint256,bytes) (runs: 256, μ: 91653, ~: 119836) +ERC1155Test:testFuzzTotalSupplyAfterSingleMint(uint256,uint256,bytes) (runs: 256, μ: 93285, ~: 119839) ERC1155Test:testFuzzTransferOwnershipNonOwner(address,address) (runs: 256, μ: 14086, ~: 14086) ERC1155Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 73957, ~: 73928) ERC1155Test:testHasOwner() (gas: 9714) @@ -266,8 +266,8 @@ ERC1155Test:testUriBaseAndTokenUriNotSet() (gas: 2768301) ERC1155Test:testUriBaseAndTokenUriSet() (gas: 65517) ERC1155Test:testUriNoBaseURI() (gas: 2818373) ERC1155Test:testUriNoTokenUri() (gas: 17407) -ERC20Invariants:invariantOwner() (runs: 256, calls: 3840, reverts: 3392) -ERC20Invariants:invariantTotalSupply() (runs: 256, calls: 3840, reverts: 3392) +ERC20Invariants:invariantOwner() (runs: 256, calls: 3840, reverts: 3390) +ERC20Invariants:invariantTotalSupply() (runs: 256, calls: 3840, reverts: 3390) ERC20Test:testApproveExceedingBalanceCase1() (gas: 40223) ERC20Test:testApproveExceedingBalanceCase2() (gas: 46478) ERC20Test:testApproveFromZeroAddress() (gas: 13220) @@ -290,26 +290,26 @@ ERC20Test:testCachedDomainSeparator() (gas: 7699) ERC20Test:testDomainSeparator() (gas: 11449) ERC20Test:testEIP712Domain() (gas: 13739) ERC20Test:testFuzzApproveSuccess(address,uint256) (runs: 256, μ: 39193, ~: 40437) -ERC20Test:testFuzzBurnFromInsufficientAllowance(address,uint256,uint8) (runs: 256, μ: 175220, ~: 175283) -ERC20Test:testFuzzBurnFromSuccess(address,uint256) (runs: 256, μ: 279935, ~: 280986) +ERC20Test:testFuzzBurnFromInsufficientAllowance(address,uint256,uint8) (runs: 256, μ: 175155, ~: 175280) +ERC20Test:testFuzzBurnFromSuccess(address,uint256) (runs: 256, μ: 280125, ~: 281154) ERC20Test:testFuzzBurnInvalidAmount(address,uint256) (runs: 256, μ: 16454, ~: 16454) -ERC20Test:testFuzzBurnSuccessCase(uint256) (runs: 256, μ: 256007, ~: 255800) +ERC20Test:testFuzzBurnSuccessCase(uint256) (runs: 256, μ: 256021, ~: 255800) ERC20Test:testFuzzDomainSeparator(uint8) (runs: 256, μ: 11665, ~: 11685) -ERC20Test:testFuzzEIP712Domain(bytes1,uint8,bytes32,uint256[]) (runs: 256, μ: 19449, ~: 19409) +ERC20Test:testFuzzEIP712Domain(bytes1,uint8,bytes32,uint256[]) (runs: 256, μ: 19444, ~: 19409) ERC20Test:testFuzzMintNonMinter(string,uint256) (runs: 256, μ: 13152, ~: 13080) -ERC20Test:testFuzzMintSuccess(string,uint256) (runs: 256, μ: 54130, ~: 55192) +ERC20Test:testFuzzMintSuccess(string,uint256) (runs: 256, μ: 54206, ~: 55192) ERC20Test:testFuzzPermitInvalid(string,string,uint16) (runs: 256, μ: 45279, ~: 45277) ERC20Test:testFuzzPermitSuccess(string,string,uint16) (runs: 256, μ: 70299, ~: 70295) ERC20Test:testFuzzRenounceOwnershipNonOwner(address) (runs: 256, μ: 13979, ~: 13979) -ERC20Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 48360, ~: 48345) +ERC20Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 48361, ~: 48345) ERC20Test:testFuzzSetMinterNonOwner(address,string) (runs: 256, μ: 15777, ~: 15704) ERC20Test:testFuzzSetMinterSuccess(string) (runs: 256, μ: 33196, ~: 33196) -ERC20Test:testFuzzTransferFromInsufficientAllowance(address,address,uint256,uint8) (runs: 256, μ: 173301, ~: 173761) -ERC20Test:testFuzzTransferFromSuccess(address,address,uint256) (runs: 256, μ: 200334, ~: 202446) +ERC20Test:testFuzzTransferFromInsufficientAllowance(address,address,uint256,uint8) (runs: 256, μ: 173482, ~: 173761) +ERC20Test:testFuzzTransferFromSuccess(address,address,uint256) (runs: 256, μ: 200080, ~: 202152) ERC20Test:testFuzzTransferInvalidAmount(address,address,uint256) (runs: 256, μ: 16849, ~: 16849) ERC20Test:testFuzzTransferOwnershipNonOwner(address,address) (runs: 256, μ: 14068, ~: 14068) -ERC20Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 73902, ~: 73874) -ERC20Test:testFuzzTransferSuccess(address,uint256) (runs: 256, μ: 172886, ~: 173875) +ERC20Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 73901, ~: 73874) +ERC20Test:testFuzzTransferSuccess(address,uint256) (runs: 256, μ: 172825, ~: 173876) ERC20Test:testHasOwner() (gas: 9758) ERC20Test:testInitialSetup() (gas: 1467701) ERC20Test:testMintNonMinter() (gas: 12639) @@ -349,20 +349,20 @@ ERC2981Test:testDeleteDefaultRoyaltyNonOwner() (gas: 10537) ERC2981Test:testFuzzDeleteDefaultRoyaltyNonOwner(address) (runs: 256, μ: 13271, ~: 13271) ERC2981Test:testFuzzRenounceOwnershipNonOwner(address) (runs: 256, μ: 13972, ~: 13972) ERC2981Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 24598, ~: 24598) -ERC2981Test:testFuzzResetTokenRoyalty(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 93597, ~: 94717) +ERC2981Test:testFuzzResetTokenRoyalty(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 93338, ~: 94699) ERC2981Test:testFuzzResetTokenRoyaltyNonOwner(address) (runs: 256, μ: 13246, ~: 13246) -ERC2981Test:testFuzzRoyaltyInfoDefaultRoyalty(address,uint256,uint256,uint96,uint256) (runs: 256, μ: 77988, ~: 79183) -ERC2981Test:testFuzzRoyaltyInfoDeleteDefaultRoyalty(address,uint256,uint256,uint96,uint256) (runs: 256, μ: 61712, ~: 62571) -ERC2981Test:testFuzzRoyaltyInfoSetTokenRoyalty(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 119876, ~: 121030) -ERC2981Test:testFuzzRoyaltyInfoSetTokenRoyaltyUpdate(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 164296, ~: 165531) -ERC2981Test:testFuzzRoyaltyInfoUpdateDefaultRoyalty(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 84143, ~: 84678) +ERC2981Test:testFuzzRoyaltyInfoDefaultRoyalty(address,uint256,uint256,uint96,uint256) (runs: 256, μ: 77900, ~: 79183) +ERC2981Test:testFuzzRoyaltyInfoDeleteDefaultRoyalty(address,uint256,uint256,uint96,uint256) (runs: 256, μ: 61643, ~: 62573) +ERC2981Test:testFuzzRoyaltyInfoSetTokenRoyalty(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 118900, ~: 121030) +ERC2981Test:testFuzzRoyaltyInfoSetTokenRoyaltyUpdate(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 162152, ~: 165531) +ERC2981Test:testFuzzRoyaltyInfoUpdateDefaultRoyalty(address,address,uint256,uint256,uint96,uint256) (runs: 256, μ: 83741, ~: 84678) ERC2981Test:testFuzzSetDefaultRoyaltyNonOwner(address) (runs: 256, μ: 15525, ~: 15525) -ERC2981Test:testFuzzSetDefaultRoyaltyTooHighFeeNumerator(uint96) (runs: 256, μ: 21342, ~: 21125) +ERC2981Test:testFuzzSetDefaultRoyaltyTooHighFeeNumerator(uint96) (runs: 256, μ: 21316, ~: 21125) ERC2981Test:testFuzzSetTokenRoyaltyInvalidReceiver(address) (runs: 256, μ: 18626, ~: 18626) ERC2981Test:testFuzzSetTokenRoyaltyNonOwner(address) (runs: 256, μ: 15565, ~: 15565) -ERC2981Test:testFuzzSetTokenRoyaltyTooHighFeeNumerator(uint96) (runs: 256, μ: 21383, ~: 21166) +ERC2981Test:testFuzzSetTokenRoyaltyTooHighFeeNumerator(uint96) (runs: 256, μ: 21357, ~: 21166) ERC2981Test:testFuzzTransferOwnershipNonOwner(address,address) (runs: 256, μ: 14039, ~: 14039) -ERC2981Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 29566, ~: 29577) +ERC2981Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 29577, ~: 29577) ERC2981Test:testHasOwner() (gas: 9688) ERC2981Test:testInitialSetup() (gas: 468824) ERC2981Test:testRenounceOwnershipNonOwner() (gas: 10871) @@ -388,8 +388,8 @@ ERC2981Test:testSupportsInterfaceSuccessGasCost() (gas: 6345) ERC2981Test:testTransferOwnershipNonOwner() (gas: 12649) ERC2981Test:testTransferOwnershipSuccess() (gas: 22091) ERC2981Test:testTransferOwnershipToZeroAddress() (gas: 15557) -ERC4626VaultInvariants:invariantTotalAssets() (runs: 256, calls: 3840, reverts: 3244) -ERC4626VaultInvariants:invariantTotalSupply() (runs: 256, calls: 3840, reverts: 3244) +ERC4626VaultInvariants:invariantTotalAssets() (runs: 256, calls: 3840, reverts: 3242) +ERC4626VaultInvariants:invariantTotalSupply() (runs: 256, calls: 3840, reverts: 3242) ERC4626VaultTest:testCachedDomainSeparator() (gas: 7676) ERC4626VaultTest:testDepositInsufficientAllowance() (gas: 82425) ERC4626VaultTest:testDepositWithNoApproval() (gas: 24740) @@ -400,10 +400,10 @@ ERC4626VaultTest:testEmptyVaultDeposit() (gas: 556789) ERC4626VaultTest:testEmptyVaultMint() (gas: 557600) ERC4626VaultTest:testEmptyVaultRedeem() (gas: 191988) ERC4626VaultTest:testEmptyVaultwithdraw() (gas: 204833) -ERC4626VaultTest:testFail_redeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 554348, ~: 557113) -ERC4626VaultTest:testFail_withdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 556261, ~: 560088) +ERC4626VaultTest:testFail_redeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 554223, ~: 558247) +ERC4626VaultTest:testFail_withdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 556033, ~: 560088) ERC4626VaultTest:testFuzzDomainSeparator(uint8) (runs: 256, μ: 11557, ~: 11577) -ERC4626VaultTest:testFuzzEIP712Domain(bytes1,uint8,bytes32,uint256[]) (runs: 256, μ: 19366, ~: 19328) +ERC4626VaultTest:testFuzzEIP712Domain(bytes1,uint8,bytes32,uint256[]) (runs: 256, μ: 19367, ~: 19328) ERC4626VaultTest:testFuzzPermitInvalid(string,string,uint16) (runs: 256, μ: 45211, ~: 45209) ERC4626VaultTest:testFuzzPermitSuccess(string,string,uint16) (runs: 256, μ: 70194, ~: 70190) ERC4626VaultTest:testInitialSetup() (gas: 5784605) @@ -424,30 +424,30 @@ ERC4626VaultTest:testVaultInteractionsForSomeoneElse() (gas: 221714) ERC4626VaultTest:testWithdrawInsufficientAllowance() (gas: 122543) ERC4626VaultTest:testWithdrawInsufficientAssets() (gas: 117830) ERC4626VaultTest:testWithdrawWithNoAssets() (gas: 21327) -ERC4626VaultTest:test_RT_deposit_redeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 473656, ~: 476219) -ERC4626VaultTest:test_RT_deposit_withdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 475496, ~: 477934) -ERC4626VaultTest:test_RT_mint_redeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 474716, ~: 476410) -ERC4626VaultTest:test_RT_mint_withdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 476458, ~: 478182) -ERC4626VaultTest:test_RT_redeem_deposit((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 473392, ~: 476462) -ERC4626VaultTest:test_RT_redeem_mint((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 473988, ~: 476655) -ERC4626VaultTest:test_RT_withdraw_deposit((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 475158, ~: 478033) -ERC4626VaultTest:test_RT_withdraw_mint((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 476278, ~: 478681) -ERC4626VaultTest:test_asset((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 423325, ~: 427727) -ERC4626VaultTest:test_convertToAssets((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 429198, ~: 432743) -ERC4626VaultTest:test_convertToShares((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 428579, ~: 432510) -ERC4626VaultTest:test_deposit((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 468470, ~: 472341) -ERC4626VaultTest:test_maxDeposit((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 423337, ~: 427740) -ERC4626VaultTest:test_maxMint((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 423362, ~: 427765) -ERC4626VaultTest:test_maxRedeem((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 423477, ~: 427879) -ERC4626VaultTest:test_maxWithdraw((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 425030, ~: 429549) -ERC4626VaultTest:test_mint((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 469577, ~: 472557) -ERC4626VaultTest:test_previewDeposit((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 466374, ~: 468752) -ERC4626VaultTest:test_previewMint((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 467591, ~: 469131) -ERC4626VaultTest:test_previewRedeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 467897, ~: 470574) -ERC4626VaultTest:test_previewWithdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 470745, ~: 472090) -ERC4626VaultTest:test_redeem((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 472309, ~: 475022) -ERC4626VaultTest:test_totalAssets((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 423927, ~: 428329) -ERC4626VaultTest:test_withdraw((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 473454, ~: 476196) +ERC4626VaultTest:test_RT_deposit_redeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 473608, ~: 475944) +ERC4626VaultTest:test_RT_deposit_withdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 475389, ~: 477933) +ERC4626VaultTest:test_RT_mint_redeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 474274, ~: 476284) +ERC4626VaultTest:test_RT_mint_withdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 476630, ~: 478151) +ERC4626VaultTest:test_RT_redeem_deposit((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 473670, ~: 476737) +ERC4626VaultTest:test_RT_redeem_mint((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 473963, ~: 476539) +ERC4626VaultTest:test_RT_withdraw_deposit((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 475427, ~: 478372) +ERC4626VaultTest:test_RT_withdraw_mint((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 476380, ~: 478560) +ERC4626VaultTest:test_asset((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 422368, ~: 427654) +ERC4626VaultTest:test_convertToAssets((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 429078, ~: 432395) +ERC4626VaultTest:test_convertToShares((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 428584, ~: 432529) +ERC4626VaultTest:test_deposit((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 468672, ~: 472487) +ERC4626VaultTest:test_maxDeposit((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 422381, ~: 427667) +ERC4626VaultTest:test_maxMint((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 422406, ~: 427692) +ERC4626VaultTest:test_maxRedeem((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 422521, ~: 427806) +ERC4626VaultTest:test_maxWithdraw((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 424074, ~: 429427) +ERC4626VaultTest:test_mint((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 469793, ~: 472627) +ERC4626VaultTest:test_previewDeposit((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 465930, ~: 468818) +ERC4626VaultTest:test_previewMint((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 467656, ~: 469248) +ERC4626VaultTest:test_previewRedeem((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 468133, ~: 470638) +ERC4626VaultTest:test_previewWithdraw((address[4],uint256[4],uint256[4],int256),uint256) (runs: 256, μ: 470392, ~: 471970) +ERC4626VaultTest:test_redeem((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 472120, ~: 474925) +ERC4626VaultTest:test_totalAssets((address[4],uint256[4],uint256[4],int256)) (runs: 256, μ: 422971, ~: 428256) +ERC4626VaultTest:test_withdraw((address[4],uint256[4],uint256[4],int256),uint256,uint256) (runs: 256, μ: 473584, ~: 476530) ERC721Invariants:invariantOwner() (runs: 256, calls: 3840, reverts: 3469) ERC721Invariants:invariantTotalSupply() (runs: 256, calls: 3840, reverts: 3469) ERC721Test:testApproveClearingApprovalWithNoPriorApproval() (gas: 177294) @@ -469,31 +469,31 @@ ERC721Test:testBurnSuccessViaApproveAndSetApprovalForAll() (gas: 371421) ERC721Test:testCachedDomainSeparator() (gas: 7699) ERC721Test:testDomainSeparator() (gas: 11450) ERC721Test:testEIP712Domain() (gas: 13877) -ERC721Test:testFuzzApproveClearingApprovalWithNoPriorApproval(address,address) (runs: 256, μ: 196799, ~: 196799) +ERC721Test:testFuzzApproveClearingApprovalWithNoPriorApproval(address,address) (runs: 256, μ: 196789, ~: 196799) ERC721Test:testFuzzApproveClearingApprovalWithPriorApproval(address,address) (runs: 256, μ: 184072, ~: 184072) ERC721Test:testFuzzApproveFromNonOwner(address) (runs: 256, μ: 172895, ~: 172895) ERC721Test:testFuzzApproveFromOperatorAddress(address,address,address) (runs: 256, μ: 222958, ~: 222958) -ERC721Test:testFuzzApproveWithNoPriorApproval(address,address) (runs: 256, μ: 196754, ~: 196754) -ERC721Test:testFuzzApproveWithPriorApproval(address,address) (runs: 256, μ: 203884, ~: 203884) +ERC721Test:testFuzzApproveWithNoPriorApproval(address,address) (runs: 256, μ: 196744, ~: 196754) +ERC721Test:testFuzzApproveWithPriorApproval(address,address) (runs: 256, μ: 203874, ~: 203884) ERC721Test:testFuzzBurnSuccess(address) (runs: 256, μ: 305615, ~: 305600) -ERC721Test:testFuzzDomainSeparator(uint8) (runs: 256, μ: 11641, ~: 11663) +ERC721Test:testFuzzDomainSeparator(uint8) (runs: 256, μ: 11643, ~: 11663) ERC721Test:testFuzzEIP712Domain(bytes1,uint8,bytes32,uint256[]) (runs: 256, μ: 19581, ~: 19542) -ERC721Test:testFuzzGetApprovedApprovedTokenId(address,address) (runs: 256, μ: 194385, ~: 194385) +ERC721Test:testFuzzGetApprovedApprovedTokenId(address,address) (runs: 256, μ: 194375, ~: 194385) ERC721Test:testFuzzPermitInvalid(string,string,uint16) (runs: 256, μ: 201667, ~: 201665) ERC721Test:testFuzzPermitSuccess(string,string,uint16) (runs: 256, μ: 227137, ~: 227133) ERC721Test:testFuzzRenounceOwnershipNonOwner(address) (runs: 256, μ: 13938, ~: 13938) -ERC721Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 48380, ~: 48364) +ERC721Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 48379, ~: 48364) ERC721Test:testFuzzSafeMintNonMinter(address) (runs: 256, μ: 15894, ~: 15894) -ERC721Test:testFuzzSafeMintSuccess(address[]) (runs: 256, μ: 21015630, ~: 20441661) -ERC721Test:testFuzzSafeTransferFromWithData(address,address,address,bytes) (runs: 256, μ: 1428908, ~: 1425307) +ERC721Test:testFuzzSafeMintSuccess(address[]) (runs: 256, μ: 20855146, ~: 20004472) +ERC721Test:testFuzzSafeTransferFromWithData(address,address,address,bytes) (runs: 256, μ: 1429054, ~: 1429893) ERC721Test:testFuzzSetApprovalForAllSuccess(address,address) (runs: 256, μ: 188481, ~: 188481) ERC721Test:testFuzzSetMinterNonOwner(address,string) (runs: 256, μ: 15822, ~: 15749) ERC721Test:testFuzzSetMinterSuccess(string) (runs: 256, μ: 33217, ~: 33216) -ERC721Test:testFuzzTokenByIndex(address,string[]) (runs: 256, μ: 21390285, ~: 21253069) -ERC721Test:testFuzzTotalSupply(address,string[]) (runs: 256, μ: 21261017, ~: 21123504) -ERC721Test:testFuzzTransferFrom(address,address,address) (runs: 256, μ: 560100, ~: 560080) +ERC721Test:testFuzzTokenByIndex(address,string[]) (runs: 256, μ: 21399845, ~: 21253069) +ERC721Test:testFuzzTotalSupply(address,string[]) (runs: 256, μ: 21270507, ~: 21123504) +ERC721Test:testFuzzTransferFrom(address,address,address) (runs: 256, μ: 560097, ~: 560080) ERC721Test:testFuzzTransferOwnershipNonOwner(address,address) (runs: 256, μ: 14090, ~: 14090) -ERC721Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 73920, ~: 73892) +ERC721Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 73922, ~: 73892) ERC721Test:testGetApprovedApprovedTokenId() (gas: 194287) ERC721Test:testGetApprovedInvalidTokenId() (gas: 11097) ERC721Test:testGetApprovedNotApprovedTokenId() (gas: 170525) @@ -556,19 +556,19 @@ ERC721Test:testTransferOwnershipToZeroAddress() (gas: 15608) MathTest:testCbrtRoundDown() (gas: 41159) MathTest:testCbrtRoundUp() (gas: 41806) MathTest:testCeilDiv() (gas: 12481) -MathTest:testFuzzCbrt(uint256,bool) (runs: 256, μ: 19431, ~: 19249) +MathTest:testFuzzCbrt(uint256,bool) (runs: 256, μ: 19443, ~: 19288) MathTest:testFuzzCeilDiv(uint256,uint256) (runs: 256, μ: 8962, ~: 8979) MathTest:testFuzzInt256Average(int256,int256) (runs: 256, μ: 5683, ~: 5683) MathTest:testFuzzLog10(uint256,bool) (runs: 256, μ: 6971, ~: 6961) -MathTest:testFuzzLog2(uint256,bool) (runs: 256, μ: 6825, ~: 6803) -MathTest:testFuzzLog256(uint256,bool) (runs: 256, μ: 6853, ~: 6831) +MathTest:testFuzzLog2(uint256,bool) (runs: 256, μ: 6826, ~: 6803) +MathTest:testFuzzLog256(uint256,bool) (runs: 256, μ: 6849, ~: 6827) MathTest:testFuzzMulDiv(uint256,uint256,uint256) (runs: 256, μ: 13038, ~: 12781) -MathTest:testFuzzMulDivDomain(uint256,uint256,uint256) (runs: 256, μ: 10485, ~: 10570) +MathTest:testFuzzMulDivDomain(uint256,uint256,uint256) (runs: 256, μ: 10488, ~: 10570) MathTest:testFuzzSignum(int256) (runs: 256, μ: 5578, ~: 5570) MathTest:testFuzzUint256Average(uint256,uint256) (runs: 256, μ: 5763, ~: 5763) -MathTest:testFuzzWadCbrt(uint256) (runs: 256, μ: 18973, ~: 18650) -MathTest:testFuzzWadExp(int256) (runs: 256, μ: 14492, ~: 14597) -MathTest:testFuzzWadLn(int256) (runs: 256, μ: 15990, ~: 15780) +MathTest:testFuzzWadCbrt(uint256) (runs: 256, μ: 18982, ~: 18667) +MathTest:testFuzzWadExp(int256) (runs: 256, μ: 14484, ~: 14597) +MathTest:testFuzzWadLn(int256) (runs: 256, μ: 15982, ~: 15766) MathTest:testInt256Average() (gas: 12010) MathTest:testLog10RoundDown() (gas: 17685) MathTest:testLog10RoundUp() (gas: 18866) @@ -589,8 +589,8 @@ MathTest:testWadExp() (gas: 24809) MathTest:testWadExpOverflow() (gas: 11127) MathTest:testWadLn() (gas: 24196) MathTest:testWadLnNegativeValues() (gas: 11130) -MerkleProofVerificationTest:testFuzzMultiProofVerifySingleLeaf(bytes32[],uint256) (runs: 256, μ: 1649976154, ~: 1649972494) -MerkleProofVerificationTest:testFuzzVerify(bytes32[],uint256) (runs: 256, μ: 135974866, ~: 135971282) +MerkleProofVerificationTest:testFuzzMultiProofVerifySingleLeaf(bytes32[],uint256) (runs: 256, μ: 1649976152, ~: 1649972613) +MerkleProofVerificationTest:testFuzzVerify(bytes32[],uint256) (runs: 256, μ: 135974864, ~: 135971401) MerkleProofVerificationTest:testFuzzVerifyMultiProofMultipleLeaves(bool,bool,bool) (runs: 256, μ: 412472467, ~: 412472462) MerkleProofVerificationTest:testInvalidMerkleMultiProof() (gas: 412478415) MerkleProofVerificationTest:testInvalidMerkleProof() (gas: 33970390) @@ -615,7 +615,7 @@ Ownable2StepInvariants:invariantPendingOwner() (runs: 256, calls: 3840, reverts: Ownable2StepTest:testAcceptOwnershipNonPendingOwner() (gas: 46604) Ownable2StepTest:testAcceptOwnershipSuccess() (gas: 39404) Ownable2StepTest:testFuzzAcceptOwnershipNonPendingOwner(address) (runs: 256, μ: 45814, ~: 45814) -Ownable2StepTest:testFuzzAcceptOwnershipSuccess(address,address) (runs: 256, μ: 65112, ~: 65084) +Ownable2StepTest:testFuzzAcceptOwnershipSuccess(address,address) (runs: 256, μ: 65113, ~: 65084) Ownable2StepTest:testFuzzPendingOwnerResetAfterRenounceOwnership(address) (runs: 256, μ: 38751, ~: 38735) Ownable2StepTest:testFuzzRenounceOwnershipNonOwner(address) (runs: 256, μ: 13954, ~: 13954) Ownable2StepTest:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 43684, ~: 43668) @@ -657,4 +657,96 @@ SignatureCheckerTest:testFuzzEIP1271WithValidSignature(string) (runs: 256, μ: 3 SignatureCheckerTest:testFuzzEOAWithInvalidSignature(bytes,string) (runs: 256, μ: 16837, ~: 16836) SignatureCheckerTest:testFuzzEOAWithInvalidSigner(string,string) (runs: 256, μ: 21466, ~: 21527) SignatureCheckerTest:testFuzzEOAWithValidSignature(string,string) (runs: 256, μ: 20585, ~: 20646) -SignatureCheckerTest:testInitialSetup() (gas: 5415) \ No newline at end of file +SignatureCheckerTest:testInitialSetup() (gas: 5415) +TimelockControllerInvariants:invariantExecutedLessThanOrEqualToScheduled() (runs: 256, calls: 3840, reverts: 1528) +TimelockControllerInvariants:invariantExecutedProposalCancellation() (runs: 256, calls: 3840, reverts: 1531) +TimelockControllerInvariants:invariantExecutingCancelledProposal() (runs: 256, calls: 3840, reverts: 1528) +TimelockControllerInvariants:invariantExecutingNotReadyProposal() (runs: 256, calls: 3840, reverts: 1535) +TimelockControllerInvariants:invariantOnceProposalExecution() (runs: 256, calls: 3840, reverts: 1485) +TimelockControllerInvariants:invariantProposalsExecutedMatchCount() (runs: 256, calls: 3840, reverts: 1528) +TimelockControllerInvariants:invariantSumOfProposals() (runs: 256, calls: 3840, reverts: 1528) +TimelockControllerTest:testAdminCannotBatchExecute() (gas: 750573) +TimelockControllerTest:testAdminCannotBatchSchedule() (gas: 748359) +TimelockControllerTest:testAdminCannotCancel() (gas: 13280) +TimelockControllerTest:testAdminCannotExecute() (gas: 18397) +TimelockControllerTest:testAdminCannotSchedule() (gas: 16069) +TimelockControllerTest:testBatchCancelFinished() (gas: 4641370) +TimelockControllerTest:testBatchEqualAndGreaterMinimumDelay() (gas: 6144529) +TimelockControllerTest:testBatchHasBeenExecuted() (gas: 4638874) +TimelockControllerTest:testBatchHasNotBeenExecuted() (gas: 3078509) +TimelockControllerTest:testBatchInsufficientDelay() (gas: 1532717) +TimelockControllerTest:testBatchMinimumDelayUpdate() (gas: 3085797) +TimelockControllerTest:testBatchOperationAlreadyScheduled() (gas: 4593338) +TimelockControllerTest:testBatchOperationIsNotReady() (gas: 4598655) +TimelockControllerTest:testBatchPendingIfExecuted() (gas: 4637848) +TimelockControllerTest:testBatchPendingIfNotYetExecuted() (gas: 3078517) +TimelockControllerTest:testBatchPredecessorInvalid() (gas: 4601007) +TimelockControllerTest:testBatchPredecessorMultipleNotExecuted() (gas: 6141737) +TimelockControllerTest:testBatchPredecessorNotExecuted() (gas: 7662956) +TimelockControllerTest:testBatchPredecessorNotScheduled() (gas: 6116865) +TimelockControllerTest:testBatchReadyAfterTheExecutionTime() (gas: 3079082) +TimelockControllerTest:testBatchReadyBeforeTheExecutionTime() (gas: 3079099) +TimelockControllerTest:testBatchReadyOnTheExecutionTime() (gas: 3078985) +TimelockControllerTest:testBatchScheduleAndExecuteWithEmptySalt() (gas: 4642907) +TimelockControllerTest:testBatchScheduleAndExecuteWithNonEmptySalt() (gas: 4646352) +TimelockControllerTest:testBatchTargetRevert() (gas: 9186500) +TimelockControllerTest:testBatchTimestampHasBeenExecuted() (gas: 4637665) +TimelockControllerTest:testBatchTimestampHasNotBeenExecuted() (gas: 3078316) +TimelockControllerTest:testCanReceiveEther() (gas: 12124) +TimelockControllerTest:testCancellerCanCancelOperation() (gas: 3064799) +TimelockControllerTest:testCompleteOperationWithAssignExecutorRoleToZeroAddress() (gas: 124673) +TimelockControllerTest:testCompletePipelineOperationMinimumDelayUpdate() (gas: 73442) +TimelockControllerTest:testCompletePipelineOperationSetRoleAdmin() (gas: 100466) +TimelockControllerTest:testExecutorCanBatchExecute() (gas: 3049249) +TimelockControllerTest:testExecutorCanExecute() (gas: 29920) +TimelockControllerTest:testExecutorCannotBatchSchedule() (gas: 1485375) +TimelockControllerTest:testExecutorCannotCancel() (gas: 15281) +TimelockControllerTest:testExecutorCannotSchedule() (gas: 19073) +TimelockControllerTest:testFuzzBatchValue(uint256) (runs: 256, μ: 4652693, ~: 4652826) +TimelockControllerTest:testFuzzHashOperation(address,uint256,bytes,bytes32,bytes32) (runs: 256, μ: 8261, ~: 8159) +TimelockControllerTest:testFuzzHashOperationBatch(address[],uint256[],bytes[],bytes32,bytes32) (runs: 256, μ: 1881454, ~: 1889945) +TimelockControllerTest:testFuzzOperationValue(uint256) (runs: 256, μ: 113151, ~: 113263) +TimelockControllerTest:testHandleERC1155() (gas: 41505969) +TimelockControllerTest:testHandleERC721() (gas: 7056837) +TimelockControllerTest:testHashOperation() (gas: 10233) +TimelockControllerTest:testHashOperationBatch() (gas: 1523421) +TimelockControllerTest:testInitialSetup() (gas: 4245443) +TimelockControllerTest:testInvalidOperation() (gas: 7856) +TimelockControllerTest:testOperationAlreadyScheduled() (gas: 52465) +TimelockControllerTest:testOperationCancelFinished() (gas: 101892) +TimelockControllerTest:testOperationEqualAndGreaterMinimumDelay() (gas: 90244) +TimelockControllerTest:testOperationHasBeenExecuted() (gas: 99429) +TimelockControllerTest:testOperationHasNotBeenExecuted() (gas: 52365) +TimelockControllerTest:testOperationInsufficientDelay() (gas: 19490) +TimelockControllerTest:testOperationMinimumDelayUpdate() (gas: 61101) +TimelockControllerTest:testOperationOperationIsNotReady() (gas: 57820) +TimelockControllerTest:testOperationPendingIfExecuted() (gas: 98359) +TimelockControllerTest:testOperationPendingIfNotYetExecuted() (gas: 52429) +TimelockControllerTest:testOperationPredecessorInvalid() (gas: 62855) +TimelockControllerTest:testOperationPredecessorMultipleNotExecuted() (gas: 92559) +TimelockControllerTest:testOperationPredecessorNotExecuted() (gas: 99291) +TimelockControllerTest:testOperationPredecessorNotScheduled() (gas: 66755) +TimelockControllerTest:testOperationReadyAfterTheExecutionTime() (gas: 52984) +TimelockControllerTest:testOperationReadyBeforeTheExecutionTime() (gas: 52927) +TimelockControllerTest:testOperationReadyOnTheExecutionTime() (gas: 52821) +TimelockControllerTest:testOperationTargetRevert() (gas: 110365) +TimelockControllerTest:testOperationTimestampHasBeenExecuted() (gas: 98112) +TimelockControllerTest:testOperationTimestampHasNotBeenExecuted() (gas: 52195) +TimelockControllerTest:testProposerCanBatchSchedule() (gas: 3088645) +TimelockControllerTest:testProposerCanCancel() (gas: 20179) +TimelockControllerTest:testProposerCanSchedule() (gas: 75659) +TimelockControllerTest:testProposerCannotBatchExecute() (gas: 1489786) +TimelockControllerTest:testProposerCannotExecute() (gas: 23599) +TimelockControllerTest:testReturnsLaterMinimumDelayForCalls() (gas: 20365) +TimelockControllerTest:testRevertWhenNotTimelock() (gas: 9053) +TimelockControllerTest:testScheduleAndExecuteWithEmptySalt() (gas: 103471) +TimelockControllerTest:testScheduleAndExecuteWithNonEmptySalt() (gas: 106828) +TimelockControllerTest:testStrangerCannotBatchExecute() (gas: 748592) +TimelockControllerTest:testStrangerCannotBatchSchedule() (gas: 746399) +TimelockControllerTest:testStrangerCannotCancel() (gas: 11276) +TimelockControllerTest:testStrangerCannotExecute() (gas: 16414) +TimelockControllerTest:testStrangerCannotSchedule() (gas: 14198) +TimelockControllerTest:testSupportsInterfaceInvalidInterfaceId() (gas: 5628) +TimelockControllerTest:testSupportsInterfaceInvalidInterfaceIdGasCost() (gas: 6418) +TimelockControllerTest:testSupportsInterfaceSuccess() (gas: 7234) +TimelockControllerTest:testSupportsInterfaceSuccessGasCost() (gas: 6525) \ No newline at end of file