Skip to content

Commit

Permalink
prevent replay
Browse files Browse the repository at this point in the history
  • Loading branch information
ezynda3 committed Nov 26, 2024
1 parent 2efd99e commit 4b3535f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/Facets/RelayFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ contract RelayFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
// Relayer wallet for ERC20 transfers
address public immutable relaySolver;

/// Storage ///

mapping(bytes32 => bool) public consumedIds;

/// Types ///

/// @dev Relay specific parameters
Expand Down Expand Up @@ -55,6 +59,11 @@ contract RelayFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
ILiFi.BridgeData memory _bridgeData,
RelayData calldata _relayData
) {
// Ensure that the id isn't already consumed
if (consumedIds[_relayData.requestId]) {
revert InvalidQuote();
}

// Verify that the bridging quote has been signed by the Relay solver
// as attested using the attestation API
// API URL: https://api.relay.link/requests/{requestId}/signature/v2
Expand Down Expand Up @@ -182,6 +191,8 @@ contract RelayFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
}
}

consumedIds[_relayData.requestId] = true;

// Emit special event if bridging to non-EVM chain
if (_bridgeData.receiver == LibAsset.NON_EVM_ADDRESS) {
emit BridgeToNonEVMChain(
Expand Down
36 changes: 35 additions & 1 deletion test/solidity/Facets/RelayFacet.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ contract TestRelayFacet is RelayFacet {
) external pure returns (uint256) {
return _getMappedChainId(chainId);
}

function setConsumedId(bytes32 id) external {
consumedIds[id] = true;
}
}

contract RelayFacetTest is TestBaseFacet {
Expand All @@ -47,7 +51,7 @@ contract RelayFacetTest is TestBaseFacet {
customBlockNumberForForking = 19767662;
initTestBase();
relayFacet = new TestRelayFacet(RELAY_RECEIVER, RELAY_SOLVER);
bytes4[] memory functionSelectors = new bytes4[](5);
bytes4[] memory functionSelectors = new bytes4[](6);
functionSelectors[0] = relayFacet.startBridgeTokensViaRelay.selector;
functionSelectors[1] = relayFacet
.swapAndStartBridgeTokensViaRelay
Expand All @@ -57,6 +61,7 @@ contract RelayFacetTest is TestBaseFacet {
.setFunctionApprovalBySignature
.selector;
functionSelectors[4] = relayFacet.getMappedChainId.selector;
functionSelectors[5] = relayFacet.setConsumedId.selector;

addFacet(diamond, address(relayFacet), functionSelectors);
relayFacet = TestRelayFacet(address(diamond));
Expand Down Expand Up @@ -170,6 +175,35 @@ contract RelayFacetTest is TestBaseFacet {
vm.stopPrank();
}

function testRevert_WhenReplayingTransactionIds() public virtual {
relayFacet.setConsumedId(validRelayData.requestId);
bridgeData.receiver = LibAsset.NON_EVM_ADDRESS;
bridgeData.destinationChainId = 1151111081099710;
validRelayData = RelayFacet.RelayData({
requestId: bytes32("1234"),
nonEVMReceiver: bytes32(
abi.encodePacked(
"EoW7FWTdPdZKpd3WAhH98c2HMGHsdh5yhzzEtk1u68Bb"
)
), // DEV Wallet
receivingAssetId: bytes32(
abi.encodePacked(
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
)
), // Solana USDC
signature: ""
});

vm.startPrank(USER_SENDER);

// approval
usdc.approve(_facetTestContractAddress, bridgeData.minAmount);

vm.expectRevert(InvalidQuote.selector);
initiateBridgeTxWithFacet(false);
vm.stopPrank();
}

function test_CanBridgeNativeTokensToSolana()
public
virtual
Expand Down

0 comments on commit 4b3535f

Please sign in to comment.