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
16 changes: 8 additions & 8 deletions contracts/SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1030,12 +1030,11 @@ abstract contract SpokePool is
* @param repaymentChainId Chain of SpokePool where relayer wants to be refunded after the challenge window has
* passed. Will receive inputAmount of the equivalent token to inputToken on the repayment chain.
*/
function fillV3Relay(V3RelayData calldata relayData, uint256 repaymentChainId)
public
override
nonReentrant
unpausedFills
{
function fillV3Relay(
V3RelayData calldata relayData,
uint256 repaymentChainId,
bytes32 repaymentAddress
) public override nonReentrant unpausedFills {
// Exclusivity deadline is inclusive and is the latest timestamp that the exclusive relayer has sole right
// to fill the relay.
if (
Expand All @@ -1055,7 +1054,7 @@ abstract contract SpokePool is
repaymentChainId: repaymentChainId
});

_fillRelayV3(relayExecution, msg.sender.toBytes32(), false);
_fillRelayV3(relayExecution, repaymentAddress, false);
}

/**
Expand All @@ -1078,6 +1077,7 @@ abstract contract SpokePool is
function fillV3RelayWithUpdatedDeposit(
V3RelayData calldata relayData,
uint256 repaymentChainId,
bytes32 repaymentAddress,
uint256 updatedOutputAmount,
bytes32 updatedRecipient,
bytes calldata updatedMessage,
Expand Down Expand Up @@ -1109,7 +1109,7 @@ abstract contract SpokePool is
UPDATE_V3_DEPOSIT_DETAILS_HASH
);

_fillRelayV3(relayExecution, msg.sender.toBytes32(), false);
_fillRelayV3(relayExecution, repaymentAddress, false);
}

/**
Expand Down
11 changes: 8 additions & 3 deletions contracts/interfaces/V3SpokePoolInterface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ interface V3SpokePoolInterface {
// to know when to send excess funds from the SpokePool to the HubPool because they can no longer be used
// for a slow fill execution.
SlowFill
// Slow fills are requested via requestSlowFill and executed by executeSlowRelayLeaf after a bundle containing
// the slow fill is validated.
}
// Slow fills are requested via requestSlowFill and executed by executeSlowRelayLeaf after a bundle containing
// the slow fill is validated.

/**************************************
* STRUCTS *
Expand Down Expand Up @@ -196,11 +196,16 @@ interface V3SpokePoolInterface {
bytes calldata depositorSignature
) external;

function fillV3Relay(V3RelayData calldata relayData, uint256 repaymentChainId) external;
function fillV3Relay(
V3RelayData calldata relayData,
uint256 repaymentChainId,
bytes32 repaymentAddress
) external;

function fillV3RelayWithUpdatedDeposit(
V3RelayData calldata relayData,
uint256 repaymentChainId,
bytes32 repaymentAddress,
uint256 updatedOutputAmount,
bytes32 updatedRecipient,
bytes calldata updatedMessage,
Expand Down
4 changes: 2 additions & 2 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const LARGE_CONTRACT_COMPILER_SETTINGS = {
settings: {
optimizer: { enabled: true, runs: 1000 },
viaIR: true,
debug: { revertStrings: isTest ? "default" : "strip" },
debug: { revertStrings: isTest ? "debug" : "strip" },
},
};
const DEFAULT_CONTRACT_COMPILER_SETTINGS = {
Expand All @@ -49,7 +49,7 @@ const DEFAULT_CONTRACT_COMPILER_SETTINGS = {
optimizer: { enabled: true, runs: 1000000 },
viaIR: true,
// Only strip revert strings if not testing or in ci.
debug: { revertStrings: isTest ? "default" : "strip" },
debug: { revertStrings: isTest ? "debug" : "strip" },
Copy link
Member Author

Choose a reason for hiding this comment

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

^

Copy link
Contributor

Choose a reason for hiding this comment

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

Very odd 🤔

},
};

Expand Down
3 changes: 2 additions & 1 deletion programs/svm-spoke/src/instructions/fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub fn fill_v3_relay(
relay_hash: [u8; 32], // include in props, while not using it, to enable us to access it from the #Instruction Attribute within the accounts. This enables us to pass in the relay_hash PDA.
relay_data: V3RelayData,
repayment_chain_id: u64,
repayment_address: Pubkey,
) -> Result<()> {
let state = &mut ctx.accounts.state;
let current_time = get_current_time(state)?;
Expand Down Expand Up @@ -165,7 +166,7 @@ pub fn fill_v3_relay(
fill_deadline: relay_data.fill_deadline,
exclusivity_deadline: relay_data.exclusivity_deadline,
exclusive_relayer: relay_data.exclusive_relayer,
relayer: *ctx.accounts.signer.key,
relayer: repayment_address,
depositor: relay_data.depositor,
recipient: relay_data.recipient,
message: relay_data.message,
Expand Down
2 changes: 1 addition & 1 deletion programs/svm-spoke/src/instructions/slow_fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ pub fn execute_v3_slow_relay_leaf(
fill_deadline: relay_data.fill_deadline,
exclusivity_deadline: relay_data.exclusivity_deadline,
exclusive_relayer: relay_data.exclusive_relayer,
relayer: *ctx.accounts.signer.key,
relayer: Pubkey::default(), // There is no repayment address for slow
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: Why are we moving from the relayer public key to address_zero here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we had it wrong and EVM implementation passes empty address as well

depositor: relay_data.depositor,
recipient: relay_data.recipient,
message: relay_data.message,
Expand Down
9 changes: 8 additions & 1 deletion programs/svm-spoke/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,15 @@ pub mod svm_spoke {
relay_hash: [u8; 32],
relay_data: V3RelayData,
repayment_chain_id: u64,
repayment_address: Pubkey,
) -> Result<()> {
instructions::fill_v3_relay(ctx, relay_hash, relay_data, repayment_chain_id)
instructions::fill_v3_relay(
ctx,
relay_hash,
relay_data,
repayment_chain_id,
repayment_address,
)
}

pub fn close_fill_pda(
Expand Down
2 changes: 1 addition & 1 deletion scripts/svm/simpleFill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ async function fillV3Relay(): Promise<void> {
}))
);

const tx = await (program.methods.fillV3Relay(Array.from(relayHashUint8Array), relayData, chainId) as any)
const tx = await (program.methods.fillV3Relay(Array.from(relayHashUint8Array), relayData, chainId, signer) as any)
.accounts({
state: statePda,
signer: signer,
Expand Down
75 changes: 55 additions & 20 deletions test/evm/hardhat/SpokePool.Relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,14 +318,17 @@ describe("SpokePool Relayer Logic", async function () {
describe("fillV3Relay", function () {
it("fills are not paused", async function () {
await spokePool.pauseFills(true);
await expect(spokePool.connect(relayer).fillV3Relay(relayData, consts.repaymentChainId)).to.be.revertedWith(
"FillsArePaused"
);
await expect(
spokePool
.connect(relayer)
.fillV3Relay(relayData, consts.repaymentChainId, hexZeroPadAddressLowercase(relayer.address))
).to.be.revertedWith("FillsArePaused");
});
it("reentrancy protected", async function () {
const functionCalldata = spokePool.interface.encodeFunctionData("fillV3Relay", [
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
]);
await expect(spokePool.connect(relayer).callback(functionCalldata)).to.be.revertedWith(
"ReentrancyGuard: reentrant call"
Expand All @@ -338,19 +341,21 @@ describe("SpokePool Relayer Logic", async function () {
exclusiveRelayer: hexZeroPadAddress(recipient.address),
exclusivityDeadline: relayData.fillDeadline,
};
await expect(spokePool.connect(relayer).fillV3Relay(_relayData, consts.repaymentChainId)).to.be.revertedWith(
"NotExclusiveRelayer"
);
await expect(
spokePool
.connect(relayer)
.fillV3Relay(_relayData, consts.repaymentChainId, hexZeroPadAddressLowercase(relayer.address))
).to.be.revertedWith("NotExclusiveRelayer");

// Can send it after exclusivity deadline
await expect(
spokePool.connect(relayer).fillV3Relay(
{
..._relayData,
exclusivityDeadline: 0,
},
consts.repaymentChainId
)
spokePool
.connect(relayer)
.fillV3Relay(
{ ..._relayData, exclusivityDeadline: 0 },
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address)
)
).to.not.be.reverted;
});
it("if no exclusive relayer is set, exclusivity deadline can be in future", async function () {
Expand All @@ -361,7 +366,11 @@ describe("SpokePool Relayer Logic", async function () {
};

// Can send it after exclusivity deadline
await expect(spokePool.connect(relayer).fillV3Relay(_relayData, consts.repaymentChainId)).to.not.be.reverted;
await expect(
spokePool
.connect(relayer)
.fillV3Relay(_relayData, consts.repaymentChainId, hexZeroPadAddressLowercase(relayer.address))
).to.not.be.reverted;
});
it("can have empty exclusive relayer before exclusivity deadline", async function () {
const _relayData = {
Expand All @@ -371,10 +380,18 @@ describe("SpokePool Relayer Logic", async function () {
};

// Can send it before exclusivity deadline if exclusive relayer is empty
await expect(spokePool.connect(relayer).fillV3Relay(_relayData, consts.repaymentChainId)).to.not.be.reverted;
await expect(
spokePool
.connect(relayer)
.fillV3Relay(_relayData, consts.repaymentChainId, hexZeroPadAddressLowercase(relayer.address))
).to.not.be.reverted;
});
it("calls _fillRelayV3 with expected params", async function () {
await expect(spokePool.connect(relayer).fillV3Relay(relayData, consts.repaymentChainId))
await expect(
spokePool
.connect(relayer)
.fillV3Relay(relayData, consts.repaymentChainId, hexZeroPadAddressLowercase(relayer.address))
)
.to.emit(spokePool, "FilledV3Relay")
.withArgs(
hexZeroPadAddressLowercase(relayData.inputToken),
Expand Down Expand Up @@ -430,6 +447,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
_relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -445,6 +463,7 @@ describe("SpokePool Relayer Logic", async function () {
exclusivityDeadline: 0,
},
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -464,6 +483,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand Down Expand Up @@ -508,6 +528,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
{ ...relayData, depositor: hexZeroPadAddress(relayer.address) },
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -530,6 +551,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -544,6 +566,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
{ ...relayData, originChainId: relayData.originChainId + 1 },
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -558,6 +581,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
{ ...relayData, depositId: relayData.depositId + 1 },
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -572,6 +596,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount.sub(1),
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -586,6 +611,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(randomAddress()),
updatedMessage,
Expand All @@ -600,6 +626,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -624,6 +651,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
{ ...relayData, depositor: hexZeroPadAddress(erc1271.address) },
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -636,6 +664,7 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
{ ...relayData, depositor: hexZeroPadAddress(erc1271.address) },
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -644,13 +673,16 @@ describe("SpokePool Relayer Logic", async function () {
).to.not.be.reverted;
});
it("cannot send updated fill after original fill", async function () {
await spokePool.connect(relayer).fillV3Relay(relayData, consts.repaymentChainId);
await spokePool
.connect(relayer)
.fillV3Relay(relayData, consts.repaymentChainId, hexZeroPadAddressLowercase(relayer.address));
await expect(
spokePool
.connect(relayer)
.fillV3RelayWithUpdatedDeposit(
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
Expand All @@ -664,14 +696,17 @@ describe("SpokePool Relayer Logic", async function () {
.fillV3RelayWithUpdatedDeposit(
relayData,
consts.repaymentChainId,
hexZeroPadAddressLowercase(relayer.address),
updatedOutputAmount,
hexZeroPadAddress(updatedRecipient),
updatedMessage,
signature
);
await expect(spokePool.connect(relayer).fillV3Relay(relayData, consts.repaymentChainId)).to.be.revertedWith(
"RelayFilled"
);
await expect(
spokePool
.connect(relayer)
.fillV3Relay(relayData, consts.repaymentChainId, hexZeroPadAddressLowercase(relayer.address))
).to.be.revertedWith("RelayFilled");
});
});
});
Expand Down
Loading
Loading