-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Enable pausing deposits and fills unilaterally #212
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,10 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall | |
// Count of deposits is used to construct a unique deposit identifier for this spoke pool. | ||
uint32 public numberOfDeposits; | ||
|
||
// Whether deposits and fills are disabled. | ||
bool public pausedFills; | ||
bool public pausedDeposits; | ||
|
||
// This contract can store as many root bundles as the HubPool chooses to publish here. | ||
RootBundle[] public rootBundles; | ||
|
||
|
@@ -121,6 +125,8 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall | |
address caller | ||
); | ||
event EmergencyDeleteRootBundle(uint256 indexed rootBundleId); | ||
event PausedDeposits(bool indexed isPaused); | ||
event PausedFills(bool indexed isPaused); | ||
|
||
/** | ||
* @notice Construct the base SpokePool. | ||
|
@@ -151,10 +157,35 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall | |
_; | ||
} | ||
|
||
modifier unpausedDeposits() { | ||
require(!pausedDeposits, "Paused deposits"); | ||
_; | ||
} | ||
|
||
modifier unpausedFills() { | ||
require(!pausedFills, "Paused fills"); | ||
_; | ||
} | ||
|
||
/************************************** | ||
* ADMIN FUNCTIONS * | ||
**************************************/ | ||
|
||
/** | ||
* @notice Pauses deposit and fill functions. This is intended to be used during upgrades or when | ||
* something goes awry. | ||
* @param pause true if the call is meant to pause the system, false if the call is meant to unpause it. | ||
*/ | ||
function pauseDeposits(bool pause) public override onlyAdmin nonReentrant { | ||
pausedDeposits = pause; | ||
emit PausedDeposits(pause); | ||
} | ||
|
||
function pauseFills(bool pause) public override onlyAdmin nonReentrant { | ||
pausedFills = pause; | ||
emit PausedFills(pause); | ||
} | ||
|
||
/** | ||
* @notice Change cross domain admin address. Callable by admin only. | ||
* @param newCrossDomainAdmin New cross domain admin. | ||
|
@@ -250,7 +281,7 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall | |
uint256 destinationChainId, | ||
uint64 relayerFeePct, | ||
uint32 quoteTimestamp | ||
) public payable override nonReentrant { | ||
) public payable override nonReentrant unpausedDeposits { | ||
// Check that deposit route is enabled. | ||
require(enabledDepositRoutes[originToken][destinationChainId], "Disabled route"); | ||
|
||
|
@@ -317,7 +348,7 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall | |
uint64 newRelayerFeePct, | ||
uint32 depositId, | ||
bytes memory depositorSignature | ||
) public override nonReentrant { | ||
) public override nonReentrant unpausedDeposits { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it desirable to make speedups subject to deposits not being paused? As I see it, the point of pausing deposits is to stop additional funds from entering the Spoke Pool. In the case of a speedup, the funds are already there, and are presumably stuck because the deposit was never filled on the destination chain. Additionally, as far as I can see, the only side-effect of a speedup is that the Spoke Pool emits another event. It's up to the bots as to whether they accept a speedup event, and it will implicitly be conditional on fills being enabled on the destination chain anyway. Based on the above, I feel like we should not apply this modifier to speedUpDeposit(). wdyt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm I think its a bit easier to reason about from the bot's perspective of all deposit related events stop once a contract is paused, even though its philosophically ok to not pause speed ups. I was thinking pausing deposits and fills is more of a bot convenience so the owner of the contracts can effectively downgrade a contract by stopping all of its events There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough - I can definitely see the argument for keeping it simple. There is a theoretical possibility for the edge case I described, and an annoying scenario would be that we have a number of underpriced deposits that are suddenly marooned in the Spoke Pool. In this case we'd need to either unpause to allow speedups to be submitted, or just take the hit and fill these relays at a discount. In theory the relayerFeePct could be very very low. It's a theoretical possibility, and probably unlikely to be a reality. As long as we're OK with the possibility of it arising then I have no additional input on this one :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm ok that's a valid concern, i don't love the idea that someone will try to use the speedup signatures to replay attack but I guess its not really an attack since they could have chosen to call |
||
require(newRelayerFeePct < 0.5e18, "invalid relayer fee"); | ||
|
||
_verifyUpdateRelayerFeeMessage(depositor, chainId(), newRelayerFeePct, depositId, depositorSignature); | ||
|
@@ -367,7 +398,7 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall | |
uint64 realizedLpFeePct, | ||
uint64 relayerFeePct, | ||
uint32 depositId | ||
) public nonReentrant { | ||
) public nonReentrant unpausedFills { | ||
// Each relay attempt is mapped to the hash of data uniquely identifying it, which includes the deposit data | ||
// such as the origin chain ID and the deposit ID, and the data in a relay attempt such as who the recipient | ||
// is, which chain and currency the recipient wants to receive funds on, and the relay fees. | ||
|
@@ -423,7 +454,7 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall | |
uint64 newRelayerFeePct, | ||
uint32 depositId, | ||
bytes memory depositorSignature | ||
) public override nonReentrant { | ||
) public override nonReentrant unpausedFills { | ||
_verifyUpdateRelayerFeeMessage(depositor, originChainId, newRelayerFeePct, depositId, depositorSignature); | ||
|
||
// Now follow the default fillRelay flow with the updated fee and the original relay hash. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Do these need to be indexed? I imagine that there will be so few of them that there's not much advantage to filtering on the "paused" state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1