Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions contracts/SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -439,18 +439,14 @@ abstract contract SpokePool is
require(amount <= MAX_TRANSFER_SIZE, "Amount too large");
require(depositCounter[originToken] <= maxCount, "Above max count");

// This function assumes that L2 timing cannot be compared accurately and consistently to L1 timing. Therefore,
// block.timestamp is different from the L1 EVM's. Therefore, the quoteTimestamp must be within a configurable
// buffer of this contract's block time to allow for this variance.
// Note also that quoteTimestamp cannot be less than the buffer otherwise the following arithmetic can result
// in underflow. This isn't a problem as the deposit will revert, but the error might be unexpected for clients.

//slither-disable-next-line timestamp
require(
getCurrentTime() >= quoteTimestamp - depositQuoteTimeBuffer &&
getCurrentTime() <= quoteTimestamp + depositQuoteTimeBuffer,
"invalid quote time"
);
// 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 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
require(getCurrentTime() - quoteTimestamp <= depositQuoteTimeBuffer, "invalid quoteTimestamp");

// Increment count of deposits so that deposit ID for this spoke pool is unique.
uint32 newDepositId = numberOfDeposits++;
Expand Down
39 changes: 21 additions & 18 deletions test/SpokePool.Deposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ describe("SpokePool Depositor Logic", async function () {
});

it("quoteTimestamp is out of range", async function () {
const revertReason = "invalid quote time";
const revertReason = "invalid quoteTimestamp";
const quoteTimeBuffer = await spokePool.depositQuoteTimeBuffer();

await expect(
Expand All @@ -301,11 +301,11 @@ describe("SpokePool Depositor Logic", async function () {
amountToDeposit,
destinationChainId,
depositRelayerFeePct,
toBN(currentSpokePoolTime).add(quoteTimeBuffer + 1),
toBN(currentSpokePoolTime).add(1),
maxUint256
)
)
).to.be.revertedWith(revertReason);
).to.be.reverted;

await expect(
spokePool
Expand All @@ -323,22 +323,25 @@ describe("SpokePool Depositor Logic", async function () {
)
).to.be.revertedWith(revertReason);

// quoteTimestamp at max age.
await expect(
spokePool
.connect(depositor)
.deposit(
...getDepositParams(
recipient.address,
erc20.address,
amountToDeposit,
destinationChainId,
depositRelayerFeePct,
currentSpokePoolTime.sub(quoteTimeBuffer),
maxUint256
// quoteTimestamp at the exact margins should succeed.
for (const offset of [0, quoteTimeBuffer]) {
await erc20.connect(depositor).approve(spokePool.address, amountToDeposit);
await expect(
spokePool
.connect(depositor)
.deposit(
...getDepositParams(
recipient.address,
erc20.address,
amountToDeposit,
destinationChainId,
depositRelayerFeePct,
currentSpokePoolTime.sub(offset),
maxUint256
)
)
)
).to.emit(spokePool, "FundsDeposited");
).to.emit(spokePool, "FundsDeposited");
}
});

it("maxCount is too low", async function () {
Expand Down