From 79c9de5d05d0e284aab741f1c4126d5c0ae09c6a Mon Sep 17 00:00:00 2001 From: 0xJabberwock <0xjabberwock@defi.sucks> Date: Thu, 8 Aug 2024 00:50:52 -0300 Subject: [PATCH] feat: arbitrable (#4) --- package.json | 4 +- remappings.txt | 2 + src/contracts/Arbitrable.sol | 106 +++++++++++++++++ src/interfaces/IArbitrable.sol | 95 +++++++++++++++ test/unit/Arbitrable.t.sol | 209 +++++++++++++++++++++++++++++++++ yarn.lock | 101 ++++------------ 6 files changed, 435 insertions(+), 82 deletions(-) create mode 100644 src/contracts/Arbitrable.sol create mode 100644 src/interfaces/IArbitrable.sol create mode 100644 test/unit/Arbitrable.t.sol diff --git a/package.json b/package.json index 1686815..eb82655 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core-contracts": "^0.0.0-e73df4c1", - "@defi-wonderland/prophet-modules-contracts": "^0.0.0-2c7deca8" + "@defi-wonderland/prophet-core-contracts": "0.0.0-438de1c5", + "@defi-wonderland/prophet-modules-contracts": "0.0.0-1197c328" }, "devDependencies": { "@commitlint/cli": "19.3.0", diff --git a/remappings.txt b/remappings.txt index 0ba2eec..2245399 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,5 +1,7 @@ forge-std/=node_modules/forge-std/src halmos-cheatcodes=node_modules/halmos-cheatcodes +@defi-wonderland/prophet-core-contracts/=node_modules/@defi-wonderland/prophet-core-contracts +@defi-wonderland/prophet-modules-contracts/=node_modules/@defi-wonderland/prophet-modules-contracts contracts/=src/contracts interfaces/=src/interfaces diff --git a/src/contracts/Arbitrable.sol b/src/contracts/Arbitrable.sol new file mode 100644 index 0000000..ada965e --- /dev/null +++ b/src/contracts/Arbitrable.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IArbitrable} from 'interfaces/IArbitrable.sol'; + +/** + * @title Arbitrable + * @notice Makes a contract subject to arbitration by The Graph + */ +abstract contract Arbitrable is IArbitrable { + address private _arbitrator; + address private _council; + address private _pendingCouncil; + + /** + * @notice Checks that the caller is The Graph's Arbitrator + */ + modifier onlyArbitrator() { + if (msg.sender != _arbitrator) revert Arbitrable_OnlyArbitrator(); + _; + } + + /** + * @notice Checks that the caller is The Graph's Council + */ + modifier onlyCouncil() { + if (msg.sender != _council) revert Arbitrable_OnlyCouncil(); + _; + } + + /** + * @notice Checks that the caller is the pending The Graph's Council + */ + modifier onlyPendingCouncil() { + if (msg.sender != _pendingCouncil) revert Arbitrable_OnlyPendingCouncil(); + _; + } + + /** + * @notice Constructor + * @param __arbitrator The address of The Graph's Arbitrator + * @param __council The address of The Graph's Council + */ + constructor(address __arbitrator, address __council) { + _setArbitrator(__arbitrator); + _setCouncil(__council); + } + + /// @inheritdoc IArbitrable + function arbitrator() public view returns (address __arbitrator) { + __arbitrator = _arbitrator; + } + + /// @inheritdoc IArbitrable + function council() public view returns (address __council) { + __council = _council; + } + + /// @inheritdoc IArbitrable + function pendingCouncil() public view returns (address __pendingCouncil) { + __pendingCouncil = _pendingCouncil; + } + + /// @inheritdoc IArbitrable + function setArbitrator(address __arbitrator) external onlyCouncil { + _setArbitrator(__arbitrator); + } + + /// @inheritdoc IArbitrable + function setPendingCouncil(address __pendingCouncil) external onlyCouncil { + _setPendingCouncil(__pendingCouncil); + } + + /// @inheritdoc IArbitrable + function confirmCouncil() external onlyPendingCouncil { + _setCouncil(_pendingCouncil); + delete _pendingCouncil; + } + + /** + * @notice Sets the address of The Graph's Arbitrator + * @param __arbitrator The address of The Graph's Arbitrator + */ + function _setArbitrator(address __arbitrator) private { + _arbitrator = __arbitrator; + emit SetArbitrator(__arbitrator); + } + + /** + * @notice Sets the address of The Graph's Council + * @param __council The address of The Graph's Council + */ + function _setCouncil(address __council) private { + _council = __council; + emit SetCouncil(__council); + } + + /** + * @notice Sets the address of the pending The Graph's Council + * @param __pendingCouncil The address of the pending The Graph's Council + */ + function _setPendingCouncil(address __pendingCouncil) private { + _pendingCouncil = __pendingCouncil; + emit SetPendingCouncil(__pendingCouncil); + } +} diff --git a/src/interfaces/IArbitrable.sol b/src/interfaces/IArbitrable.sol new file mode 100644 index 0000000..5d98b9e --- /dev/null +++ b/src/interfaces/IArbitrable.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/** + * @title Arbitrable + * @notice Makes a contract subject to arbitration by The Graph + */ +interface IArbitrable { + /*/////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Emitted when The Graph's Arbitrator is set + * @param _arbitrator The address of The Graph's Arbitrator + */ + event SetArbitrator(address _arbitrator); + + /** + * @notice Emitted when The Graph's Council is set + * @param _council The address of The Graph's Council + */ + event SetCouncil(address _council); + + /** + * @notice Emitted when the pending The Graph's Council is set + * @param _pendingCouncil The address of the pending The Graph's Council + */ + event SetPendingCouncil(address _pendingCouncil); + + /*/////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Thrown when the caller is not The Graph's Arbitrator + */ + error Arbitrable_OnlyArbitrator(); + + /** + * @notice Thrown when the caller is not The Graph's Council + */ + error Arbitrable_OnlyCouncil(); + + /** + * @notice Thrown when the caller is not the pending The Graph's Council + */ + error Arbitrable_OnlyPendingCouncil(); + + /*/////////////////////////////////////////////////////////////// + VARIABLES + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Returns the address of The Graph's Arbitrator + * @return _arbitrator The address of The Graph's Arbitrator + */ + function arbitrator() external view returns (address _arbitrator); + + /** + * @notice Returns the address of The Graph's Council + * @return _council The address of The Graph's Council + */ + function council() external view returns (address _council); + + /** + * @notice Returns the address of the pending The Graph's Council + * @return _pendingCouncil The address of the pending The Graph's Council + */ + function pendingCouncil() external view returns (address _pendingCouncil); + + /*/////////////////////////////////////////////////////////////// + LOGIC + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Changes the address of The Graph's Arbitrator + * @dev Callable only by The Graph's Council + * @param _arbitrator The address of The Graph's Arbitrator + */ + function setArbitrator(address _arbitrator) external; + + /** + * @notice Sets the address of the pending The Graph's Council + * @dev Callable only by The Graph's Council + * @param _pendingCouncil The address of the pending The Graph's Council + */ + function setPendingCouncil(address _pendingCouncil) external; + + /** + * @notice Changes the address of The Graph's Council to the pending one + * @dev Callable only by the pending The Graph's Council + */ + function confirmCouncil() external; +} diff --git a/test/unit/Arbitrable.t.sol b/test/unit/Arbitrable.t.sol new file mode 100644 index 0000000..a8433c1 --- /dev/null +++ b/test/unit/Arbitrable.t.sol @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IArbitrable} from 'interfaces/IArbitrable.sol'; + +import {Arbitrable} from 'contracts/Arbitrable.sol'; + +import 'forge-std/Test.sol'; + +contract ArbitrableMock is Arbitrable { + constructor(address _arbitrator, address _council) Arbitrable(_arbitrator, _council) {} + + // solhint-disable-next-line no-empty-blocks + function mockOnlyArbitrator() external onlyArbitrator {} + + // solhint-disable-next-line no-empty-blocks + function mockOnlyCouncil() external onlyCouncil {} + + // solhint-disable-next-line no-empty-blocks + function mockOnlyPendingCouncil() external onlyPendingCouncil {} +} + +contract Arbitrable_Unit_BaseTest is Test { + using stdStorage for StdStorage; + + ArbitrableMock public arbitrable; + + address public arbitrator; + address public council; + address public pendingCouncil; + + event SetArbitrator(address _arbitrator); + event SetCouncil(address _council); + event SetPendingCouncil(address _pendingCouncil); + + function setUp() public { + arbitrator = makeAddr('Arbitrator'); + council = makeAddr('Council'); + pendingCouncil = makeAddr('PendingCouncil'); + + arbitrable = new ArbitrableMock(arbitrator, council); + } + + function _mockPendingCouncil(address _pendingCouncil) internal { + stdstore.target(address(arbitrable)).sig(IArbitrable.pendingCouncil.selector).checked_write(_pendingCouncil); + } +} + +contract Arbitrable_Unit_Constructor is Arbitrable_Unit_BaseTest { + function test_setArbitrator(address _arbitrator, address _council) public { + arbitrable = new ArbitrableMock(_arbitrator, _council); + + assertEq(arbitrable.arbitrator(), _arbitrator); + } + + function test_emitSetArbitrator(address _arbitrator, address _council) public { + vm.expectEmit(); + emit SetArbitrator(_arbitrator); + new ArbitrableMock(_arbitrator, _council); + } + + function test_setCouncil(address _arbitrator, address _council) public { + arbitrable = new ArbitrableMock(_arbitrator, _council); + + assertEq(arbitrable.council(), _council); + } + + function test_emitSetCouncil(address _arbitrator, address _council) public { + vm.expectEmit(); + emit SetCouncil(_council); + new ArbitrableMock(_arbitrator, _council); + } +} + +contract Arbitrable_Unit_SetArbitrator is Arbitrable_Unit_BaseTest { + modifier happyPath() { + vm.startPrank(council); + _; + } + + function test_revertOnlyCouncil(address _arbitrator) public happyPath { + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyCouncil.selector); + arbitrable.setArbitrator(_arbitrator); + } + + function test_setArbitrator(address _arbitrator) public happyPath { + arbitrable.setArbitrator(_arbitrator); + + assertEq(arbitrable.arbitrator(), _arbitrator); + } + + function test_emitSetArbitrator(address _arbitrator) public happyPath { + vm.expectEmit(); + emit SetArbitrator(_arbitrator); + arbitrable.setArbitrator(_arbitrator); + } +} + +contract Arbitrable_Unit_SetPendingCouncil is Arbitrable_Unit_BaseTest { + modifier happyPath() { + vm.startPrank(council); + _; + } + + function test_revertOnlyCouncil(address _pendingCouncil) public happyPath { + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyCouncil.selector); + arbitrable.setPendingCouncil(_pendingCouncil); + } + + function test_setPendingCouncil(address _pendingCouncil) public happyPath { + arbitrable.setPendingCouncil(_pendingCouncil); + + assertEq(arbitrable.pendingCouncil(), _pendingCouncil); + } + + function test_emitSetPendingCouncil(address _pendingCouncil) public happyPath { + vm.expectEmit(); + emit SetPendingCouncil(_pendingCouncil); + arbitrable.setPendingCouncil(_pendingCouncil); + } +} + +contract Arbitrable_Unit_ConfirmCouncil is Arbitrable_Unit_BaseTest { + modifier happyPath() { + _mockPendingCouncil(pendingCouncil); + + vm.startPrank(pendingCouncil); + _; + } + + function test_revertOnlyPendingCouncil() public happyPath { + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyPendingCouncil.selector); + arbitrable.confirmCouncil(); + } + + function test_setCouncil() public happyPath { + arbitrable.confirmCouncil(); + + assertEq(arbitrable.council(), pendingCouncil); + } + + function test_emitSetCouncil() public happyPath { + vm.expectEmit(); + emit SetCouncil(pendingCouncil); + arbitrable.confirmCouncil(); + } + + function test_deletePendingCouncil() public happyPath { + arbitrable.confirmCouncil(); + + assertEq(arbitrable.pendingCouncil(), address(0)); + } +} + +contract Arbitrable_Unit_OnlyArbitrator is Arbitrable_Unit_BaseTest { + modifier happyPath() { + vm.startPrank(arbitrator); + _; + } + + function test_revertOnlyArbitrator() public { + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyArbitrator.selector); + arbitrable.mockOnlyArbitrator(); + } + + function test_onlyArbitrator() public happyPath { + arbitrable.mockOnlyArbitrator(); + } +} + +contract Arbitrable_Unit_OnlyCouncil is Arbitrable_Unit_BaseTest { + modifier happyPath() { + vm.startPrank(council); + _; + } + + function test_revertOnlyCouncil() public { + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyCouncil.selector); + arbitrable.mockOnlyCouncil(); + } + + function test_onlyCouncil() public happyPath { + arbitrable.mockOnlyCouncil(); + } +} + +contract Arbitrable_Unit_OnlyPendingCouncil is Arbitrable_Unit_BaseTest { + modifier happyPath() { + _mockPendingCouncil(pendingCouncil); + + vm.startPrank(pendingCouncil); + _; + } + + function test_revertOnlyPendingCouncil() public { + vm.stopPrank(); + vm.expectRevert(IArbitrable.Arbitrable_OnlyPendingCouncil.selector); + arbitrable.mockOnlyPendingCouncil(); + } + + function test_onlyPendingCouncil() public happyPath { + arbitrable.mockOnlyPendingCouncil(); + } +} diff --git a/yarn.lock b/yarn.lock index 8f853f3..f10f820 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,49 +190,25 @@ solc-typed-ast "18.1.2" yargs "17.7.2" -"@defi-wonderland/prophet-core-contracts@0.0.0-a8dc38de": - version "0.0.0-a8dc38de" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-a8dc38de.tgz#3e662bc423887bc1bf12ac44a2c15346b56b6957" - integrity sha512-W0OG+bNBSunUvqeFPxlC/IzfxWwE9CpebBRSfOB9MP+7Wivn3KLtzD7neIFSxmWFDT479YBp715ZnTa87Lr6fQ== - dependencies: - "@defi-wonderland/solidity-utils" "0.0.0-3e9c8e8b" - "@openzeppelin/contracts" "^4.9.3" - ds-test "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - forge-std "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" +"@defi-wonderland/prophet-core-contracts@0.0.0-438de1c5": + version "0.0.0-438de1c5" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-438de1c5.tgz#2b0238636c89eb71b07d57e12abfdea57c53b03b" + integrity sha512-UqdNRr2eH5DNSQ7qUriZbvR9LoXLXDMKTOjcjTTc8Gbq1aVcBhwFu4mSdrnhpQkXHjKtmsO0IfGcRHIGLvnXSQ== + +"@defi-wonderland/prophet-core-contracts@0.0.0-d01bc1a0": + version "0.0.0-d01bc1a0" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-d01bc1a0.tgz#ee4e8d970289a26966f6565b2f691d68d7b4232a" + integrity sha512-n4Dl1QgQAZafOtV7ef/fSoew2qlxWSdS389Z6PdIn7LxrHrzzRJi+nmJ1DJazMvMuhk/0dZbMhnaXMBi05E1zQ== + +"@defi-wonderland/prophet-modules-contracts@0.0.0-1197c328": + version "0.0.0-1197c328" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-1197c328.tgz#f58aa52a5a33fb39a9404bdf5e16ab75fcdde85f" + integrity sha512-78IRF5dSoHvVIzS9/NSqkuQrzPLrVKzRnBvOeSWt/vzoKy3Pm6rkcT5qzWZynIXbFNyMXGTa8HKYBWKFNlaE9A== + dependencies: + "@defi-wonderland/prophet-core-contracts" "0.0.0-d01bc1a0" + "@openzeppelin/contracts" "4.9.5" solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" -"@defi-wonderland/prophet-core-contracts@^0.0.0-e73df4c1": - version "0.0.0-e73df4c1" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core-contracts/-/prophet-core-contracts-0.0.0-e73df4c1.tgz#b5006963fe45c9079fc4a17d638f7199146ba5a2" - integrity sha512-7dFJ2xHXlbZQHYxYLkmkHf7RCpRahbPKt8bOJzUC/As6VpH8tNzwgV6+O1Ih+g77DIFqDUXdWgfaAB432USotA== - dependencies: - "@defi-wonderland/solidity-utils" "0.0.0-3e9c8e8b" - "@openzeppelin/contracts" "^4.9.3" - ds-test "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - forge-std "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" - -"@defi-wonderland/prophet-modules-contracts@^0.0.0-2c7deca8": - version "0.0.0-2c7deca8" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-modules-contracts/-/prophet-modules-contracts-0.0.0-2c7deca8.tgz#ae3461200039c62c655b291f7ce6d90011cb0ef5" - integrity sha512-ZK194P+TQUgs50CT0BudgSvadX8DOr8ZFzAfDnOyBY9BGkDDi9ztdE6Ff7BbytXm4wPr+9G1bVDNoTH4XvLu4Q== - dependencies: - "@defi-wonderland/prophet-core-contracts" "0.0.0-a8dc38de" - "@defi-wonderland/solidity-utils" "0.0.0-3e9c8e8b" - "@openzeppelin/contracts" "^4.9.3" - ds-test "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - forge-std "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - solmate "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" - -"@defi-wonderland/solidity-utils@0.0.0-3e9c8e8b": - version "0.0.0-3e9c8e8b" - resolved "https://registry.yarnpkg.com/@defi-wonderland/solidity-utils/-/solidity-utils-0.0.0-3e9c8e8b.tgz#1f9c47506e1679ea36d0854e9aa69bd210af4da0" - integrity sha512-HCN5TTO58jTrLrAcxXwTPm++P0u4dMDnwVkssszoEu0SmVKwegzZOdoA+gNbfOjjYydph+3+9bAZbNXj+UK2rg== - dependencies: - "@openzeppelin/contracts" "4.9.2" - ds-test "https://github.com/dapphub/ds-test" - forge-std "https://github.com/foundry-rs/forge-std" - "@noble/curves@1.3.0", "@noble/curves@~1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" @@ -266,15 +242,10 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@openzeppelin/contracts@4.9.2": - version "4.9.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.2.tgz#1cb2d5e4d3360141a17dbc45094a8cad6aac16c1" - integrity sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg== - -"@openzeppelin/contracts@^4.9.3": - version "4.9.6" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677" - integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA== +"@openzeppelin/contracts@4.9.5": + version "4.9.5" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.5.tgz#1eed23d4844c861a1835b5d33507c1017fa98de8" + integrity sha512-ZK+W5mVhRppff9BE6YdR8CC52C8zAvsVAiWhEtQ5+oNxFE6h1WdeWo+FJSF8KKvtxxVYZ7MTP/5KoVpAU3aSWg== "@scure/base@~1.1.4": version "1.1.6" @@ -702,20 +673,6 @@ dot-prop@^5.1.0: dependencies: is-obj "^2.0.0" -"ds-test@git+https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0": - version "1.0.0" - uid e282159d5170298eb2455a6c05280ab5a73a4ef0 - resolved "git+https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - -"ds-test@https://github.com/dapphub/ds-test": - version "1.0.0" - uid e282159d5170298eb2455a6c05280ab5a73a4ef0 - resolved "https://github.com/dapphub/ds-test#e282159d5170298eb2455a6c05280ab5a73a4ef0" - -"ds-test@https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0": - version "1.0.0" - resolved "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" - emoji-regex@^10.3.0: version "10.3.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23" @@ -868,22 +825,10 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -"forge-std@git+https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e": - version "1.5.6" - resolved "git+https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - "forge-std@github:foundry-rs/forge-std#1.8.2": version "1.8.2" resolved "https://codeload.github.com/foundry-rs/forge-std/tar.gz/978ac6fadb62f5f0b723c996f64be52eddba6801" -"forge-std@https://github.com/foundry-rs/forge-std": - version "1.9.1" - resolved "https://github.com/foundry-rs/forge-std#2cbff0602d340503dba9828ab6981053704d1384" - -"forge-std@https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e": - version "1.5.6" - resolved "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -1784,10 +1729,6 @@ solhint-community@4.0.0: version "6.1.0" resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" -"solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c": - version "6.1.0" - resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" - sort-object-keys@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45"