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
36 changes: 36 additions & 0 deletions contracts/SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,42 @@ abstract contract SpokePool is
);
}

/**
* @notice This is a simple wrapper for deposit() that sets the quoteTimestamp to the current SpokePool timestamp.
* @notice This function is intended for multisig depositors who can accept some LP fee uncertainty in order to lift
* the quoteTimestamp buffer constraint.
* @dev Re-orgs may produce invalid fills if the quoteTimestamp moves across a change in HubPool utilisation.
* @dev The existing function modifiers are already enforced by deposit(), so no additional modifiers are imposed.
* @param recipient Address to receive funds at on destination chain.
* @param originToken Token to lock into this contract to initiate deposit.
* @param amount Amount of tokens to deposit. Will be amount of tokens to receive less fees.
* @param destinationChainId Denotes network where user will receive funds from SpokePool by a relayer.
* @param relayerFeePct % of deposit amount taken out to incentivize a fast relayer.
* @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.
* Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.
* @param maxCount used to protect the depositor from frontrunning to guarantee their quote remains valid.
*/
function depositNow(
address recipient,
address originToken,
uint256 amount,
uint256 destinationChainId,
int64 relayerFeePct,
bytes memory message,
uint256 maxCount
) public payable {
deposit(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you'll need to pass through the msg.value to deposit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msg.value propagates because the call to deposit() is internal, but I've added tests to verify this: 9499d4e.

recipient,
originToken,
amount,
destinationChainId,
relayerFeePct,
uint32(getCurrentTime()),
message,
maxCount
);
}

/**
* @notice Convenience method that depositor can use to signal to relayer to use updated fee.
* @notice Relayer should only use events emitted by this function to submit fills with updated fees, otherwise they
Expand Down
10 changes: 10 additions & 0 deletions contracts/interfaces/SpokePoolInterface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ interface SpokePoolInterface {
uint256 maxCount
) external payable;

function depositNow(
address recipient,
address originToken,
uint256 amount,
uint256 destinationChainId,
int64 relayerFeePct,
bytes memory message,
uint256 maxCount
) external payable;

function speedUpDeposit(
address depositor,
int64 updatedRelayerFeePct,
Expand Down
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const config: HardhatUserConfig = {
"contracts/Boba_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS,
"contracts/Optimism_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS,
"contracts/Base_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS,
"contracts/Polygon_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS,
"contracts/test/MockSpokePoolV2.sol": LARGE_CONTRACT_COMPILER_SETTINGS,
"contracts/test/MockOptimism_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS,
},
Expand Down
62 changes: 62 additions & 0 deletions test/SpokePool.Deposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,68 @@ describe("SpokePool Depositor Logic", async function () {
).to.emit(spokePool, "FundsDeposited");
});

it("quoteTimestamp is set correctly by depositNow()", async function () {
// ERC20 deposit
await expect(
spokePool
.connect(depositor)
.depositNow(
recipient.address,
erc20.address,
amountToDeposit.toString(),
destinationChainId.toString(),
depositRelayerFeePct.toString(),
"0x",
maxUint256
)
)
.to.emit(spokePool, "FundsDeposited")
.withArgs(
amountToDeposit,
destinationChainId,
destinationChainId,
depositRelayerFeePct,
0,
currentSpokePoolTime,
erc20.address,
recipient.address,
depositor.address,
"0x"
);

// Native token deposit - amount != msg.value
await expect(
spokePool
.connect(depositor)
.depositNow(
recipient.address,
weth.address,
amountToDeposit.toString(),
destinationChainId.toString(),
depositRelayerFeePct.toString(),
"0x",
maxUint256,
{ value: amountToDeposit.add(1) }
)
).to.be.revertedWith("msg.value must match amount");

// Native token deposit - amount == msg.value.
await expect(() =>
spokePool
.connect(depositor)
.depositNow(
recipient.address,
weth.address,
amountToDeposit.toString(),
destinationChainId.toString(),
depositRelayerFeePct.toString(),
"0x",
maxUint256,
{ value: amountToDeposit }
)
).to.changeEtherBalances([depositor, weth], [amountToDeposit.mul(toBN("-1")), amountToDeposit]);
});

it("maxCount is too low", async function () {
const revertReason = "Above max count";

Expand Down