diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d291a5..6f73ca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [0.17.0](https://github.com/propeller-heads/tycho-execution/compare/0.16.0...0.17.0) (2025-01-27) + + +### Features + +* add pause/unpause methods ([c982ed9](https://github.com/propeller-heads/tycho-execution/commit/c982ed99e8bd1a01ec637aa1b9cd2c5ae69ddac4)) + + +### Bug Fixes + +* ci ([4ee337d](https://github.com/propeller-heads/tycho-execution/commit/4ee337d1ee3fa5cda7bbec64b760e39028165a60)) +* test pauser ([5734b53](https://github.com/propeller-heads/tycho-execution/commit/5734b535548338adcd3a738feb559b5b16105766)) + ## [0.16.0](https://github.com/propeller-heads/tycho-execution/compare/0.15.0...0.16.0) (2025-01-27) diff --git a/Cargo.lock b/Cargo.lock index 67969c5..1bfe46c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4163,7 +4163,7 @@ dependencies = [ [[package]] name = "tycho-execution" -version = "0.16.0" +version = "0.17.0" dependencies = [ "alloy", "alloy-primitives", diff --git a/Cargo.toml b/Cargo.toml index ba4c9f2..1065e67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-execution" -version = "0.16.0" +version = "0.17.0" edition = "2021" [dependencies] diff --git a/foundry/src/TychoRouter.sol b/foundry/src/TychoRouter.sol index bf4ba36..f929e9b 100644 --- a/foundry/src/TychoRouter.sol +++ b/foundry/src/TychoRouter.sol @@ -7,6 +7,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@permit2/src/interfaces/IAllowanceTransfer.sol"; import "./ExecutionDispatcher.sol"; import "./CallbackVerificationDispatcher.sol"; +import "@openzeppelin/contracts/utils/Pausable.sol"; error TychoRouter__WithdrawalFailed(); error TychoRouter__AddressZero(); @@ -14,7 +15,8 @@ error TychoRouter__AddressZero(); contract TychoRouter is AccessControl, ExecutionDispatcher, - CallbackVerificationDispatcher + CallbackVerificationDispatcher, + Pausable { IAllowanceTransfer public immutable permit2; @@ -27,6 +29,8 @@ contract TychoRouter is 0xe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f88182060; bytes32 public constant PAUSER_ROLE = 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a; + bytes32 public constant UNPAUSER_ROLE = + 0x427da25fe773164f88948d3e215c94b6554e2ed5e5f203a821c9f2f6131cf75a; bytes32 public constant FUND_RESCUER_ROLE = 0x912e45d663a6f4cc1d0491d8f046e06c616f40352565ea1cdb86a0e1aaefa41b; @@ -58,6 +62,20 @@ contract TychoRouter is // TODO execute generic callback } + /** + * @dev Pauses the contract + */ + function pause() external onlyRole(PAUSER_ROLE) { + _pause(); + } + + /** + * @dev Unpauses the contract + */ + function unpause() external onlyRole(UNPAUSER_ROLE) { + _unpause(); + } + /** * @dev Executes a swap graph supporting internal splits token amount * splits, checking that the user gets more than minUserAmount of buyToken. @@ -72,7 +90,7 @@ contract TychoRouter is bytes calldata swaps, IAllowanceTransfer.PermitSingle calldata permitSingle, bytes calldata signature - ) external returns (uint256 amountOut) { + ) external whenNotPaused returns (uint256 amountOut) { amountOut = 0; // TODO } diff --git a/foundry/test/Constants.sol b/foundry/test/Constants.sol index 058a27a..ed1b66f 100644 --- a/foundry/test/Constants.sol +++ b/foundry/test/Constants.sol @@ -10,9 +10,12 @@ contract Constants is Test { address FEE_SETTER = makeAddr("feeSetter"); address FEE_RECEIVER = makeAddr("feeReceiver"); - // dummy contracts + // Dummy contracts address DUMMY = makeAddr("dummy"); + address PAUSER = makeAddr("pauser"); + address UNPAUSER = makeAddr("unpauser"); + // Assets address WETH_ADDR = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); address DAI_ADDR = address(0x6B175474E89094C44Da98b954EedeAC495271d0F); diff --git a/foundry/test/TychoRouter.t.sol b/foundry/test/TychoRouter.t.sol index c6f0386..3d6f6d0 100644 --- a/foundry/test/TychoRouter.t.sol +++ b/foundry/test/TychoRouter.t.sol @@ -163,4 +163,30 @@ contract TychoRouterTest is TychoRouterTestSetup { tychoRouter.setFeeReceiver(FEE_RECEIVER); vm.stopPrank(); } + + function testPause() public { + vm.startPrank(PAUSER); + assertEq(tychoRouter.paused(), false); + tychoRouter.pause(); + assertEq(tychoRouter.paused(), true); + // TODO: test swap calls when implemeted + vm.stopPrank(); + + vm.startPrank(UNPAUSER); + tychoRouter.unpause(); + assertEq(tychoRouter.paused(), false); + vm.stopPrank(); + + vm.startPrank(UNPAUSER); + vm.expectRevert(); + tychoRouter.unpause(); + vm.stopPrank(); + } + + function testPauseNonRole() public { + vm.startPrank(BOB); + vm.expectRevert(); + tychoRouter.pause(); + vm.stopPrank(); + } } diff --git a/foundry/test/TychoRouterTestSetup.sol b/foundry/test/TychoRouterTestSetup.sol index a97e3a9..8958313 100644 --- a/foundry/test/TychoRouterTestSetup.sol +++ b/foundry/test/TychoRouterTestSetup.sol @@ -17,6 +17,8 @@ contract TychoRouterTestSetup is Test, Constants { tychoRouter.grantRole(keccak256("EXECUTOR_SETTER_ROLE"), BOB); tychoRouter.grantRole(keccak256("FUND_RESCUER_ROLE"), FUND_RESCUER); tychoRouter.grantRole(keccak256("FEE_SETTER_ROLE"), FEE_SETTER); + tychoRouter.grantRole(keccak256("PAUSER_ROLE"), PAUSER); + tychoRouter.grantRole(keccak256("UNPAUSER_ROLE"), UNPAUSER); executorSetter = BOB; deployDummyContract(); vm.stopPrank(); diff --git a/test/TychoRouter.t.sol b/test/TychoRouter.t.sol new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/test/TychoRouter.t.sol @@ -0,0 +1 @@ + \ No newline at end of file