From 388a828d96b649aa0047436b8dc889fd9137463e Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Tue, 7 Feb 2023 17:44:05 -0500 Subject: [PATCH 1/2] DRAFT: self relay Signed-off-by: Matt Rice --- contracts/SpokePool.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contracts/SpokePool.sol b/contracts/SpokePool.sol index eb2ad56e5..8e169e3c4 100644 --- a/contracts/SpokePool.sol +++ b/contracts/SpokePool.sol @@ -822,6 +822,12 @@ abstract contract SpokePool is SpokePoolInterface, Testable, Lockable, MultiCall // fill any relay up to 100 tokens, and partial fill with 100 tokens for larger relays). relayFills[relayHash] += fillAmountPreFees; + // If relayer and receiver are the same address, there is no need to do any transfer, as it would result in no + // net movement of funds. + // Note: this is important because it means that relayers can intentionally self-relay in a capital efficient + // way (no need to have funds on the destination). + if (msg.sender == relayData.recipient) return fillAmountPreFees; + // If relay token is wrappedNativeToken then unwrap and send native token. if (relayData.destinationToken == address(wrappedNativeToken)) { // Note: useContractFunds is True if we want to send funds to the recipient directly out of this contract, From f73912999ea8640c372469c3c53f8a3dd8dc281b Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Tue, 21 Feb 2023 05:24:05 -0500 Subject: [PATCH 2/2] add test Signed-off-by: Matt Rice --- test/SpokePool.Relay.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/SpokePool.Relay.ts b/test/SpokePool.Relay.ts index de308ebd7..5aeb6bbd1 100644 --- a/test/SpokePool.Relay.ts +++ b/test/SpokePool.Relay.ts @@ -125,6 +125,27 @@ describe("SpokePool Relayer Logic", async function () { // Fill amount should be set. expect(await spokePool.relayFills(relayHash)).to.equal(consts.amountToRelayPreFees); }); + it("Self-relay transfers no tokens", async function () { + const largeRelayAmount = consts.amountToSeedWallets.mul(100); + const { relayHash, relayData } = getRelayHash( + depositor.address, + relayer.address, + consts.firstDepositId, + consts.originChainId, + consts.destinationChainId, + weth.address, + largeRelayAmount + ); + + // This should work, despite the amount being quite large. + await spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, largeRelayAmount)); + + // Balance should be the same as before. + expect(await weth.balanceOf(relayer.address)).to.equal(consts.amountToSeedWallets); + + // Fill amount should be set. + expect(await spokePool.relayFills(relayHash)).to.equal(largeRelayAmount); + }); it("General failure cases", async function () { // Fees set too high. await expect(