From a40017f579fe72f564cf845fe6c454fe5f6928e9 Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Mon, 3 Feb 2025 17:31:50 -0500 Subject: [PATCH] Revert "improve(SpokePool): _depositV3 interprets `exclusivityParameter` as an offset, or a timestamp (#670)" This reverts commit fac5dd1dac63ac1a80f0f6a97b6b6e246693f4f6. --- contracts/SpokePool.sol | 187 ++++++------------ contracts/interfaces/V3SpokePoolInterface.sol | 2 +- test/evm/hardhat/SpokePool.Deposit.ts | 173 +--------------- test/evm/hardhat/SpokePool.Relay.ts | 22 ++- test/evm/hardhat/SpokePool.SlowRelay.ts | 7 +- test/evm/hardhat/constants.ts | 2 - 6 files changed, 92 insertions(+), 301 deletions(-) diff --git a/contracts/SpokePool.sol b/contracts/SpokePool.sol index 6c009dcbf..412b422c6 100644 --- a/contracts/SpokePool.sol +++ b/contracts/SpokePool.sol @@ -144,10 +144,6 @@ abstract contract SpokePool is // token for the input token. By using this magic value, off-chain validators do not have to keep // this event in their lookback window when querying for expired deposts. uint32 public constant INFINITE_FILL_DEADLINE = type(uint32).max; - - // One year in seconds. If `exclusivityParameter` is set to a value less than this, then the emitted - // exclusivityDeadline in a deposit event will be set to the current time plus this value. - uint32 public constant MAX_EXCLUSIVITY_PERIOD_SECONDS = 31_536_000; /**************************************** * EVENTS * ****************************************/ @@ -433,8 +429,9 @@ abstract contract SpokePool is /** * @notice Previously, this function allowed the caller to specify the exclusivityDeadline, otherwise known as the * as exact timestamp on the destination chain before which only the exclusiveRelayer could fill the deposit. Now, - * the caller is expected to pass in a number that will be interpreted either as an offset or a fixed - * timestamp depending on its value. + * the caller is expected to pass in an exclusivityPeriod which is the number of seconds to be added to the + * block.timestamp to produce the exclusivityDeadline. This allows the caller to ignore any latency associated + * with this transaction being mined and propagating this transaction to the miner. * @notice Request to bridge input token cross chain to a destination chain and receive a specified amount * of output tokens. The fee paid to relayers and the system should be captured in the spread between output * amount and input amount when adjusted to be denominated in the input token. A relayer on the destination @@ -473,17 +470,9 @@ abstract contract SpokePool is * @param fillDeadline The deadline for the relayer to fill the deposit. After this destination chain timestamp, * the fill will revert on the destination chain. Must be set between [currentTime, currentTime + fillDeadlineBuffer] * where currentTime is block.timestamp on this chain or this transaction will revert. - * @param exclusivityParameter This value is used to set the exclusivity deadline timestamp in the emitted deposit - * event. Before this destinationchain timestamp, only the exclusiveRelayer (if set to a non-zero address), - * can fill this deposit. There are three ways to use this parameter: - * 1. NO EXCLUSIVITY: If this value is set to 0, then a timestamp of 0 will be emitted, - * meaning that there is no exclusivity period. - * 2. OFFSET: If this value is less than MAX_EXCLUSIVITY_PERIOD_SECONDS, then add this value to - * the block.timestamp to derive the exclusive relayer deadline. Note that using the parameter in this way - * will expose the filler of the deposit to the risk that the block.timestamp of this event gets changed - * due to a chain-reorg, which would also change the exclusivity timestamp. - * 3. TIMESTAMP: Otherwise, set this value as the exclusivity deadline timestamp. - * which is the deadline for the exclusiveRelayer to fill the deposit. + * @param exclusivityPeriod Added to the current time to set the exclusive relayer deadline, + * which is the deadline for the exclusiveRelayer to fill the deposit. After this destination chain timestamp, + * anyone can fill the deposit. * @param message The message to send to the recipient on the destination chain if the recipient is a contract. * If the message is not empty, the recipient contract must implement handleV3AcrossMessage() or the fill will revert. */ @@ -498,23 +487,62 @@ abstract contract SpokePool is address exclusiveRelayer, uint32 quoteTimestamp, uint32 fillDeadline, - uint32 exclusivityParameter, + uint32 exclusivityPeriod, bytes calldata message ) public payable override nonReentrant unpausedDeposits { - _depositV3( - depositor, - recipient, + // Check that deposit route is enabled for the input token. There are no checks required for the output token + // which is pulled from the relayer at fill time and passed through this contract atomically to the recipient. + if (!enabledDepositRoutes[inputToken][destinationChainId]) revert DisabledRoute(); + + // Require that quoteTimestamp has a maximum age so that depositors pay an LP fee based on recent HubPool usage. + // It is assumed that cross-chain timestamps are normally loosely in-sync, but clock drift can occur. If the + // SpokePool time stalls or lags significantly, it is still possible to make deposits by setting quoteTimestamp + // within the configured buffer. The owner should pause deposits/fills if this is undesirable. + // This will underflow if quoteTimestamp is more than depositQuoteTimeBuffer; + // this is safe but will throw an unintuitive error. + + // slither-disable-next-line timestamp + uint256 currentTime = getCurrentTime(); + if (currentTime - quoteTimestamp > depositQuoteTimeBuffer) revert InvalidQuoteTimestamp(); + + // fillDeadline is relative to the destination chain. + // Don’t allow fillDeadline to be more than several bundles into the future. + // This limits the maximum required lookback for dataworker and relayer instances. + // Also, don't allow fillDeadline to be in the past. This poses a potential UX issue if the destination + // chain time keeping and this chain's time keeping are out of sync but is not really a practical hurdle + // unless they are significantly out of sync or the depositor is setting very short fill deadlines. This latter + // situation won't be a problem for honest users. + if (fillDeadline < currentTime || fillDeadline > currentTime + fillDeadlineBuffer) revert InvalidFillDeadline(); + + // If the address of the origin token is a wrappedNativeToken contract and there is a msg.value with the + // transaction then the user is sending the native token. In this case, the native token should be + // wrapped. + if (inputToken == address(wrappedNativeToken) && msg.value > 0) { + if (msg.value != inputAmount) revert MsgValueDoesNotMatchInputAmount(); + wrappedNativeToken.deposit{ value: msg.value }(); + // Else, it is a normal ERC20. In this case pull the token from the caller as per normal. + // Note: this includes the case where the L2 caller has WETH (already wrapped ETH) and wants to bridge them. + // In this case the msg.value will be set to 0, indicating a "normal" ERC20 bridging action. + } else { + // msg.value should be 0 if input token isn't the wrapped native token. + if (msg.value != 0) revert MsgValueDoesNotMatchInputAmount(); + IERC20Upgradeable(inputToken).safeTransferFrom(msg.sender, address(this), inputAmount); + } + + emit V3FundsDeposited( inputToken, outputToken, inputAmount, outputAmount, destinationChainId, - exclusiveRelayer, // Increment count of deposits so that deposit ID for this spoke pool is unique. numberOfDeposits++, quoteTimestamp, fillDeadline, - exclusivityParameter, + uint32(currentTime) + exclusivityPeriod, + depositor, + recipient, + exclusiveRelayer, message ); } @@ -735,9 +763,7 @@ abstract contract SpokePool is * - fillDeadline The deadline for the caller to fill the deposit. After this timestamp, * the fill will revert on the destination chain. * - exclusivityDeadline: The deadline for the exclusive relayer to fill the deposit. After this - * timestamp, anyone can fill this deposit. Note that if this value was set in depositV3 by adding an offset - * to the deposit's block.timestamp, there is re-org risk for the caller of this method because the event's - * block.timestamp can change. Read the comments in `depositV3` about the `exclusivityParameter` for more details. + * timestamp, anyone can fill this deposit. * - message The message to send to the recipient if the recipient is a contract that implements a * handleV3AcrossMessage() public function * @param repaymentChainId Chain of SpokePool where relayer wants to be refunded after the challenge window has @@ -752,7 +778,7 @@ abstract contract SpokePool is // Exclusivity deadline is inclusive and is the latest timestamp that the exclusive relayer has sole right // to fill the relay. if ( - _fillIsExclusive(relayData.exclusivityDeadline, uint32(getCurrentTime())) && + _fillIsExclusive(relayData.exclusiveRelayer, relayData.exclusivityDeadline, uint32(getCurrentTime())) && relayData.exclusiveRelayer != msg.sender ) { revert NotExclusiveRelayer(); @@ -798,7 +824,7 @@ abstract contract SpokePool is // Exclusivity deadline is inclusive and is the latest timestamp that the exclusive relayer has sole right // to fill the relay. if ( - _fillIsExclusive(relayData.exclusivityDeadline, uint32(getCurrentTime())) && + _fillIsExclusive(relayData.exclusiveRelayer, relayData.exclusivityDeadline, uint32(getCurrentTime())) && relayData.exclusiveRelayer != msg.sender ) { revert NotExclusiveRelayer(); @@ -847,7 +873,7 @@ abstract contract SpokePool is // fast fill within this deadline. Moreover, the depositor should expect to get *fast* filled within // this deadline, not slow filled. As a simplifying assumption, we will not allow slow fills to be requested // during this exclusivity period. - if (_fillIsExclusive(relayData.exclusivityDeadline, currentTime)) { + if (_fillIsExclusive(relayData.exclusiveRelayer, relayData.exclusivityDeadline, currentTime)) { revert NoSlowFillsInExclusivityWindow(); } if (relayData.fillDeadline < currentTime) revert ExpiredFillDeadline(); @@ -1022,99 +1048,6 @@ abstract contract SpokePool is * INTERNAL FUNCTIONS * **************************************/ - function _depositV3( - address depositor, - address recipient, - address inputToken, - address outputToken, - uint256 inputAmount, - uint256 outputAmount, - uint256 destinationChainId, - address exclusiveRelayer, - uint32 depositId, - uint32 quoteTimestamp, - uint32 fillDeadline, - uint32 exclusivityParameter, - bytes calldata message - ) internal { - // Check that deposit route is enabled for the input token. There are no checks required for the output token - // which is pulled from the relayer at fill time and passed through this contract atomically to the recipient. - if (!enabledDepositRoutes[inputToken][destinationChainId]) revert DisabledRoute(); - - // Require that quoteTimestamp has a maximum age so that depositors pay an LP fee based on recent HubPool usage. - // It is assumed that cross-chain timestamps are normally loosely in-sync, but clock drift can occur. If the - // SpokePool time stalls or lags significantly, it is still possible to make deposits by setting quoteTimestamp - // within the configured buffer. The owner should pause deposits/fills if this is undesirable. - // This will underflow if quoteTimestamp is more than depositQuoteTimeBuffer; - // this is safe but will throw an unintuitive error. - - // slither-disable-next-line timestamp - uint256 currentTime = getCurrentTime(); - if (currentTime - quoteTimestamp > depositQuoteTimeBuffer) revert InvalidQuoteTimestamp(); - - // fillDeadline is relative to the destination chain. - // Don’t allow fillDeadline to be more than several bundles into the future. - // This limits the maximum required lookback for dataworker and relayer instances. - // Also, don't allow fillDeadline to be in the past. This poses a potential UX issue if the destination - // chain time keeping and this chain's time keeping are out of sync but is not really a practical hurdle - // unless they are significantly out of sync or the depositor is setting very short fill deadlines. This latter - // situation won't be a problem for honest users. - if (fillDeadline < currentTime || fillDeadline > currentTime + fillDeadlineBuffer) revert InvalidFillDeadline(); - - // There are three cases for setting the exclusivity deadline using the exclusivity parameter: - // 1. If this parameter is 0, then there is no exclusivity period and emit 0 for the deadline. This - // means that fillers of this deposit do not have to worry about the block.timestamp of this event changing - // due to re-orgs when filling this deposit. - // 2. If the exclusivity parameter is less than or equal to MAX_EXCLUSIVITY_PERIOD_SECONDS, then the exclusivity - // deadline is set to the block.timestamp of this event plus the exclusivity parameter. This means that the - // filler of this deposit assumes re-org risk when filling this deposit because the block.timestamp of this - // event affects the exclusivity deadline. - // 3. Otherwise, interpret this parameter as a timestamp and emit it as the exclusivity deadline. This means - // that the filler of this deposit will not assume re-org risk related to the block.timestamp of this - // event changing. - uint32 exclusivityDeadline = exclusivityParameter; - if (exclusivityDeadline > 0) { - if (exclusivityDeadline <= MAX_EXCLUSIVITY_PERIOD_SECONDS) { - exclusivityDeadline += uint32(currentTime); - } - - // As a safety measure, prevent caller from inadvertently locking funds during exclusivity period - // by forcing them to specify an exclusive relayer. - if (exclusiveRelayer == address(0)) revert InvalidExclusiveRelayer(); - } - - // If the address of the origin token is a wrappedNativeToken contract and there is a msg.value with the - // transaction then the user is sending the native token. In this case, the native token should be - // wrapped. - if (inputToken == address(wrappedNativeToken) && msg.value > 0) { - if (msg.value != inputAmount) revert MsgValueDoesNotMatchInputAmount(); - wrappedNativeToken.deposit{ value: msg.value }(); - // Else, it is a normal ERC20. In this case pull the token from the caller as per normal. - // Note: this includes the case where the L2 caller has WETH (already wrapped ETH) and wants to bridge them. - // In this case the msg.value will be set to 0, indicating a "normal" ERC20 bridging action. - } else { - // msg.value should be 0 if input token isn't the wrapped native token. - if (msg.value != 0) revert MsgValueDoesNotMatchInputAmount(); - IERC20Upgradeable(inputToken).safeTransferFrom(msg.sender, address(this), inputAmount); - } - - emit V3FundsDeposited( - inputToken, - outputToken, - inputAmount, - outputAmount, - destinationChainId, - depositId, - quoteTimestamp, - fillDeadline, - exclusivityDeadline, - depositor, - recipient, - exclusiveRelayer, - message - ); - } - function _deposit( address depositor, address recipient, @@ -1426,9 +1359,13 @@ abstract contract SpokePool is } } - // Determine whether the exclusivityDeadline implies active exclusivity. - function _fillIsExclusive(uint32 exclusivityDeadline, uint32 currentTime) internal pure returns (bool) { - return exclusivityDeadline >= currentTime; + // Determine whether the combination of exlcusiveRelayer and exclusivityDeadline implies active exclusivity. + function _fillIsExclusive( + address exclusiveRelayer, + uint32 exclusivityDeadline, + uint32 currentTime + ) internal pure returns (bool) { + return exclusivityDeadline >= currentTime && exclusiveRelayer != address(0); } // Implementing contract needs to override this to ensure that only the appropriate cross chain admin can execute diff --git a/contracts/interfaces/V3SpokePoolInterface.sol b/contracts/interfaces/V3SpokePoolInterface.sol index dd490cd1b..d004fdfcc 100644 --- a/contracts/interfaces/V3SpokePoolInterface.sol +++ b/contracts/interfaces/V3SpokePoolInterface.sol @@ -222,7 +222,7 @@ interface V3SpokePoolInterface { error DisabledRoute(); error InvalidQuoteTimestamp(); error InvalidFillDeadline(); - error InvalidExclusiveRelayer(); + error InvalidExclusivityDeadline(); error MsgValueDoesNotMatchInputAmount(); error NotExclusiveRelayer(); error NoSlowFillsInExclusivityWindow(); diff --git a/test/evm/hardhat/SpokePool.Deposit.ts b/test/evm/hardhat/SpokePool.Deposit.ts index 0069bac77..8e7714c18 100644 --- a/test/evm/hardhat/SpokePool.Deposit.ts +++ b/test/evm/hardhat/SpokePool.Deposit.ts @@ -25,7 +25,6 @@ import { amountReceived, MAX_UINT32, originChainId, - MAX_EXCLUSIVITY_OFFSET_SECONDS, zeroAddress, } from "./constants"; @@ -435,170 +434,6 @@ describe("SpokePool Depositor Logic", async function () { ) ).to.not.be.reverted; }); - it("invalid exclusivity params", async function () { - const currentTime = await spokePool.getCurrentTime(); - - // If exclusive deadline is not zero, then exclusive relayer must be set. - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData({ - ...relayData, - exclusiveRelayer: zeroAddress, - exclusivityDeadline: 1, - }) - ) - ).to.be.revertedWith("InvalidExclusiveRelayer"); - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData({ - ...relayData, - exclusiveRelayer: zeroAddress, - exclusivityDeadline: MAX_EXCLUSIVITY_OFFSET_SECONDS, - }) - ) - ).to.be.revertedWith("InvalidExclusiveRelayer"); - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData({ - ...relayData, - exclusiveRelayer: zeroAddress, - exclusivityDeadline: MAX_EXCLUSIVITY_OFFSET_SECONDS + 1, - }) - ) - ).to.be.revertedWith("InvalidExclusiveRelayer"); - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData({ - ...relayData, - exclusiveRelayer: zeroAddress, - exclusivityDeadline: currentTime.sub(1), - }) - ) - ).to.be.revertedWith("InvalidExclusiveRelayer"); - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData({ - ...relayData, - exclusiveRelayer: zeroAddress, - exclusivityDeadline: currentTime.add(1), - }) - ) - ).to.be.revertedWith("InvalidExclusiveRelayer"); - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData({ - ...relayData, - exclusiveRelayer: zeroAddress, - exclusivityDeadline: 0, - }) - ) - ).to.not.be.reverted; - }); - it("exclusivity param is used as an offset", async function () { - const currentTime = (await spokePool.getCurrentTime()).toNumber(); - const fillDeadlineOffset = 1000; - const exclusivityDeadlineOffset = MAX_EXCLUSIVITY_OFFSET_SECONDS; - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData( - { - ...relayData, - exclusiveRelayer: depositor.address, - exclusivityDeadline: exclusivityDeadlineOffset, - }, - undefined, - currentTime - ) - ) - ) - .to.emit(spokePool, "V3FundsDeposited") - .withArgs( - relayData.inputToken, - relayData.outputToken, - relayData.inputAmount, - relayData.outputAmount, - destinationChainId, - // deposit ID is 0 for first deposit - 0, - currentTime, // quoteTimestamp should be current time - currentTime + fillDeadlineOffset, // fillDeadline should be current time + offset - currentTime + exclusivityDeadlineOffset, // exclusivityDeadline should be current time + offset - relayData.depositor, - relayData.recipient, - depositor.address, - relayData.message - ); - }); - it("exclusivity param is used as a timestamp", async function () { - const currentTime = (await spokePool.getCurrentTime()).toNumber(); - const fillDeadlineOffset = 1000; - const exclusivityDeadlineTimestamp = MAX_EXCLUSIVITY_OFFSET_SECONDS + 1; - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData( - { - ...relayData, - exclusiveRelayer: depositor.address, - exclusivityDeadline: exclusivityDeadlineTimestamp, - }, - undefined, - currentTime - ) - ) - ) - .to.emit(spokePool, "V3FundsDeposited") - .withArgs( - relayData.inputToken, - relayData.outputToken, - relayData.inputAmount, - relayData.outputAmount, - destinationChainId, - // deposit ID is 0 for first deposit - 0, - currentTime, // quoteTimestamp should be current time - currentTime + fillDeadlineOffset, // fillDeadline should be current time + offset - exclusivityDeadlineTimestamp, // exclusivityDeadline should be passed in time - relayData.depositor, - relayData.recipient, - depositor.address, - relayData.message - ); - }); - it("exclusivity param is set to 0", async function () { - const currentTime = (await spokePool.getCurrentTime()).toNumber(); - const fillDeadlineOffset = 1000; - const zeroExclusivity = 0; - await expect( - spokePool.connect(depositor).depositV3( - ...getDepositArgsFromRelayData( - { - ...relayData, - exclusiveRelayer: depositor.address, - exclusivityDeadline: zeroExclusivity, - }, - undefined, - currentTime - ) - ) - ) - .to.emit(spokePool, "V3FundsDeposited") - .withArgs( - relayData.inputToken, - relayData.outputToken, - relayData.inputAmount, - relayData.outputAmount, - destinationChainId, - // deposit ID is 0 for first deposit - 0, - currentTime, // quoteTimestamp should be current time - currentTime + fillDeadlineOffset, // fillDeadline should be current time + offset - 0, // Exclusivity deadline should always be 0 - relayData.depositor, - relayData.recipient, - depositor.address, - relayData.message - ); - }); it("if input token is WETH and msg.value > 0, msg.value must match inputAmount", async function () { await expect( spokePool @@ -669,7 +504,7 @@ describe("SpokePool Depositor Logic", async function () { 0, currentTime, // quoteTimestamp should be current time currentTime + fillDeadlineOffset, // fillDeadline should be current time + offset - 0, + currentTime, relayData.depositor, relayData.recipient, relayData.exclusiveRelayer, @@ -677,6 +512,7 @@ describe("SpokePool Depositor Logic", async function () { ); }); it("emits V3FundsDeposited event with correct deposit ID", async function () { + const currentTime = (await spokePool.getCurrentTime()).toNumber(); await expect(spokePool.connect(depositor).depositV3(...depositArgs)) .to.emit(spokePool, "V3FundsDeposited") .withArgs( @@ -689,7 +525,7 @@ describe("SpokePool Depositor Logic", async function () { 0, quoteTimestamp, relayData.fillDeadline, - 0, + currentTime, relayData.depositor, relayData.recipient, relayData.exclusiveRelayer, @@ -701,6 +537,7 @@ describe("SpokePool Depositor Logic", async function () { expect(await spokePool.numberOfDeposits()).to.equal(1); }); it("tokens are always pulled from caller, even if different from specified depositor", async function () { + const currentTime = (await spokePool.getCurrentTime()).toNumber(); const balanceBefore = await erc20.balanceOf(depositor.address); const newDepositor = randomAddress(); await expect( @@ -718,7 +555,7 @@ describe("SpokePool Depositor Logic", async function () { 0, quoteTimestamp, relayData.fillDeadline, - 0, + currentTime, // New depositor newDepositor, relayData.recipient, diff --git a/test/evm/hardhat/SpokePool.Relay.ts b/test/evm/hardhat/SpokePool.Relay.ts index 88ca7de91..88c0aeaf3 100644 --- a/test/evm/hardhat/SpokePool.Relay.ts +++ b/test/evm/hardhat/SpokePool.Relay.ts @@ -349,6 +349,26 @@ describe("SpokePool Relayer Logic", async function () { ) ).to.not.be.reverted; }); + it("if no exclusive relayer is set, exclusivity deadline can be in future", async function () { + const _relayData = { + ...relayData, + // Overwrite exclusivity deadline + exclusivityDeadline: relayData.fillDeadline, + }; + + // Can send it after exclusivity deadline + await expect(spokePool.connect(relayer).fillV3Relay(_relayData, consts.repaymentChainId)).to.not.be.reverted; + }); + it("can have empty exclusive relayer before exclusivity deadline", async function () { + const _relayData = { + ...relayData, + // Overwrite exclusivity deadline + exclusivityDeadline: relayData.fillDeadline, + }; + + // Can send it before exclusivity deadline if exclusive relayer is empty + await expect(spokePool.connect(relayer).fillV3Relay(_relayData, consts.repaymentChainId)).to.not.be.reverted; + }); it("calls _fillRelayV3 with expected params", async function () { await expect(spokePool.connect(relayer).fillV3Relay(relayData, consts.repaymentChainId)) .to.emit(spokePool, "FilledV3Relay") @@ -400,7 +420,7 @@ describe("SpokePool Relayer Logic", async function () { spokePool.connect(relayer).fillV3RelayWithUpdatedDeposit( { ...relayData, - exclusivityDeadline: 0, + exclusiveRelayer: consts.zeroAddress, }, consts.repaymentChainId, updatedOutputAmount, diff --git a/test/evm/hardhat/SpokePool.SlowRelay.ts b/test/evm/hardhat/SpokePool.SlowRelay.ts index c72dcad09..4a0ded716 100644 --- a/test/evm/hardhat/SpokePool.SlowRelay.ts +++ b/test/evm/hardhat/SpokePool.SlowRelay.ts @@ -54,10 +54,9 @@ describe("SpokePool Slow Relay Logic", async function () { it("in absence of exclusivity", async function () { // Clock drift between spokes can mean exclusivityDeadline is in future even when no exclusivity was applied. await spokePool.setCurrentTime(relayData.exclusivityDeadline - 1); - await expect(spokePool.connect(relayer).requestV3SlowFill({ ...relayData, exclusivityDeadline: 0 })).to.emit( - spokePool, - "RequestedV3SlowFill" - ); + await expect( + spokePool.connect(relayer).requestV3SlowFill({ ...relayData, exclusiveRelayer: consts.zeroAddress }) + ).to.emit(spokePool, "RequestedV3SlowFill"); }); it("during exclusivity deadline", async function () { await spokePool.setCurrentTime(relayData.exclusivityDeadline); diff --git a/test/evm/hardhat/constants.ts b/test/evm/hardhat/constants.ts index 14c2f6075..cb4bf6de3 100644 --- a/test/evm/hardhat/constants.ts +++ b/test/evm/hardhat/constants.ts @@ -100,8 +100,6 @@ export const l1TokenTransferThreshold = toWei(100); export const MAX_UINT32 = BigNumber.from("0xFFFFFFFF"); -export const MAX_EXCLUSIVITY_OFFSET_SECONDS = 24 * 60 * 60 * 365; // 1 year - // DAI's Rate model. export const sampleRateModel = { UBar: toWei(0.8).toString(),