Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: EVM changes required to support Solana #672

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
6b4d8bc
feat(chain-adapters): add solana adapter (#641)
Reinis-FRP Oct 18, 2024
c4153c4
Merge branch 'master' into svm-dev
chrismaree Oct 18, 2024
9201079
Merge branch 'master' into svm-dev
chrismaree Oct 18, 2024
5a54ddb
feat: address to bytes32 contract changes (#650)
md0x Oct 21, 2024
c338c54
Merge branch 'master' into svm-dev
chrismaree Oct 21, 2024
aa36eb6
feat: Add relayer repayment address (#653)
chrismaree Oct 22, 2024
1afdf1e
fix: clean up cast utilities (#676)
chrismaree Oct 22, 2024
7a85081
feat: update spokepool relayer refund to handle blocked transfers (#675)
chrismaree Oct 28, 2024
d94686d
WIP
chrismaree Nov 1, 2024
3e7cb6c
WIP
chrismaree Nov 1, 2024
18df9a0
Merge branch 'master' into svm-dev
md0x Nov 7, 2024
231b509
fix(evm): merkle tree tests bytes32
md0x Nov 7, 2024
75d1699
Merge branch 'master' into svm-dev
chrismaree Nov 9, 2024
38be8e0
WIP
chrismaree Nov 9, 2024
b223f6c
feat(svm): svm-dev fixes from review (#727)
md0x Nov 19, 2024
58b09d3
Merge branch 'master' into svm-dev
md0x Nov 20, 2024
3d0e899
test: fix forge tests
md0x Nov 20, 2024
1ff7bb1
proposal: ensure that EVM errors are always consistant on underflows …
chrismaree Nov 22, 2024
d36f9e6
feat: revert bytes32 conversion for internal functions (#755)
md0x Nov 22, 2024
848e043
WIP
chrismaree Nov 22, 2024
3c2ab40
Discard changes to contracts/Ovm_SpokePool.sol
chrismaree Nov 23, 2024
a89be73
fix: stack too deep (#766)
md0x Nov 25, 2024
656578a
WIP
chrismaree Nov 25, 2024
56dca16
WIP
chrismaree Nov 25, 2024
5c566fb
WIP
chrismaree Nov 25, 2024
f80e188
Revert "feat: update depositor to bytes32" (#764)
md0x Nov 25, 2024
740d44f
Merge branch 'master' into svm-dev
chrismaree Nov 25, 2024
c9d0837
Merge branch 'svm-dev' of github.com:across-protocol/contracts into s…
chrismaree Nov 25, 2024
79bf5b8
Discard changes to contracts/PolygonZkEVM_SpokePool.sol
chrismaree Nov 25, 2024
aa48a3d
Discard changes to contracts/Polygon_SpokePool.sol
chrismaree Nov 25, 2024
e582cb7
Merge branch 'master' into svm-dev
chrismaree Nov 25, 2024
44bfd94
fix: make event case consistant between evm & svm (#760)
chrismaree Nov 25, 2024
d1f7a3a
feat(SpokePool): Remove depositExclusive (#642)
nicholaspai Nov 25, 2024
9905481
feat: Introduce opt-in deterministic relay data hashes (again) (#639)
mrice32 Nov 25, 2024
6e18091
Merge branch 'master' into svm-dev
mrice32 Nov 25, 2024
48d65d4
docs: fix comment duplication (#775)
md0x Nov 25, 2024
0691f0a
fix: emit hashed message in evm fill events (#772)
Reinis-FRP Nov 25, 2024
9a93d49
Merge branch 'master' into svm-dev
Reinis-FRP Nov 25, 2024
0f2600f
fix: linting
Reinis-FRP Nov 25, 2024
fa137a2
feat: improve _getV3RelayHash method (#779)
chrismaree Dec 3, 2024
0396330
Merge branch 'master' into svm-dev
chrismaree Dec 3, 2024
8e8370f
WIP
chrismaree Dec 3, 2024
af4c107
WIP
chrismaree Dec 3, 2024
401e24c
Merge branch 'master' into svm-dev
chrismaree Dec 4, 2024
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
663 changes: 506 additions & 157 deletions contracts/SpokePool.sol

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions contracts/SpokePoolVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Address.sol";
import "./interfaces/V3SpokePoolInterface.sol";
import { AddressToBytes32 } from "./libraries/AddressConverters.sol";

/**
* @notice SpokePoolVerifier is a contract that verifies that the SpokePool exists on this chain before sending ETH to it.
Expand All @@ -14,6 +15,7 @@ import "./interfaces/V3SpokePoolInterface.sol";
*/
contract SpokePoolVerifier {
using Address for address;
using AddressToBytes32 for address;

error InvalidMsgValue();
error InvalidSpokePool();
Expand Down Expand Up @@ -42,12 +44,12 @@ contract SpokePoolVerifier {
*/
function deposit(
V3SpokePoolInterface spokePool,
address recipient,
address inputToken,
bytes32 recipient,
bytes32 inputToken,
uint256 inputAmount,
uint256 outputAmount,
uint256 destinationChainId,
address exclusiveRelayer,
bytes32 exclusiveRelayer,
uint32 quoteTimestamp,
uint32 fillDeadline,
uint32 exclusivityDeadline,
Expand All @@ -57,12 +59,12 @@ contract SpokePoolVerifier {
if (!address(spokePool).isContract()) revert InvalidSpokePool();
// Set msg.sender as the depositor so that msg.sender can speed up the deposit.
spokePool.depositV3{ value: msg.value }(
msg.sender,
msg.sender.toBytes32(),
recipient,
inputToken,
// @dev Setting outputToken to 0x0 to instruct fillers to use the equivalent token
// as the originToken on the destination chain.
address(0),
bytes32(0),
inputAmount,
outputAmount,
destinationChainId,
Expand Down
12 changes: 7 additions & 5 deletions contracts/SwapAndBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import "./Lockable.sol";
import "@uma/core/contracts/common/implementation/MultiCaller.sol";
import "./libraries/AddressConverters.sol";

/**
* @title SwapAndBridgeBase
Expand All @@ -18,6 +19,7 @@ import "@uma/core/contracts/common/implementation/MultiCaller.sol";
*/
abstract contract SwapAndBridgeBase is Lockable, MultiCaller {
using SafeERC20 for IERC20;
using AddressToBytes32 for address;

// This contract performs a low level call with arbirary data to an external contract. This is a large attack
// surface and we should whitelist which function selectors are allowed to be called on the exchange.
Expand Down Expand Up @@ -182,14 +184,14 @@ abstract contract SwapAndBridgeBase is Lockable, MultiCaller {
) internal {
_acrossInputToken.safeIncreaseAllowance(address(spokePool), _acrossInputAmount);
spokePool.depositV3(
depositData.depositor,
depositData.recipient,
address(_acrossInputToken), // input token
depositData.outputToken, // output token
depositData.depositor.toBytes32(),
depositData.recipient.toBytes32(),
address(_acrossInputToken).toBytes32(), // input token
depositData.outputToken.toBytes32(), // output token
_acrossInputAmount, // input amount.
depositData.outputAmount, // output amount
depositData.destinationChainid,
depositData.exclusiveRelayer,
depositData.exclusiveRelayer.toBytes32(),
depositData.quoteTimestamp,
depositData.fillDeadline,
depositData.exclusivityDeadline,
Expand Down
190 changes: 190 additions & 0 deletions contracts/chain-adapters/Solana_Adapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import { IMessageTransmitter, ITokenMessenger } from "../external/interfaces/CCTPInterfaces.sol";
import { SpokePoolInterface } from "../interfaces/SpokePoolInterface.sol";
import { AdapterInterface } from "./interfaces/AdapterInterface.sol";
import { CircleCCTPAdapter, CircleDomainIds } from "../libraries/CircleCCTPAdapter.sol";
import { Bytes32ToAddress } from "../libraries/AddressConverters.sol";

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
* @notice Contract containing logic to send messages from L1 to Solana via CCTP.
* @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be
* called via delegatecall, which will execute this contract's logic within the context of the originating contract.
* For example, the HubPool will delegatecall these functions, therefore it's only necessary that the HubPool's methods
* that call this contract's logic guard against reentrancy.
* @custom:security-contact [email protected]
*/

// solhint-disable-next-line contract-name-camelcase
contract Solana_Adapter is AdapterInterface, CircleCCTPAdapter {
Copy link
Contributor

Choose a reason for hiding this comment

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

How much of this contract is specific to Solana vs could be used with any chain we connect to via CCTP?

I haven't gone deep on the specifics, but, for instance, can we build an adapter that could be used just as well with an EVM chain like BSC?

Copy link
Contributor

Choose a reason for hiding this comment

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

It is quite specific in a sense that it must be aware of Solana token model where recipient SpokePool address needs to be translated to its corresponding vault token address.

/**
* @notice We use Bytes32ToAddress library to map a Solana address to an Ethereum address representation.
* @dev The Ethereum address is derived from the Solana address by truncating it to its lowest 20 bytes. This same
* conversion must be done by the HubPool owner when adding Solana spoke pool and setting the corresponding pool
* rebalance and deposit routes.
*/
using Bytes32ToAddress for bytes32;

/**
* @notice The official Circle CCTP MessageTransmitter contract endpoint.
* @dev Posted officially here: https://developers.circle.com/stablecoins/docs/evm-smart-contracts
*/
// solhint-disable-next-line immutable-vars-naming
IMessageTransmitter public immutable cctpMessageTransmitter;

// Solana spoke pool address, decoded from Base58 to bytes32.
bytes32 public immutable SOLANA_SPOKE_POOL_BYTES32;

// Solana spoke pool address, mapped to its EVM address representation.
address public immutable SOLANA_SPOKE_POOL_ADDRESS;

// USDC mint address on Solana, decoded from Base58 to bytes32.
bytes32 public immutable SOLANA_USDC_BYTES32;

// USDC mint address on Solana, mapped to its EVM address representation.
address public immutable SOLANA_USDC_ADDRESS;

// USDC token address on Solana for the spoke pool (vault ATA), decoded from Base58 to bytes32.
bytes32 public immutable SOLANA_SPOKE_POOL_USDC_VAULT;

// Custom errors for constructor argument validation.
error InvalidCctpTokenMessenger(address tokenMessenger);
error InvalidCctpMessageTransmitter(address messageTransmitter);

// Custom errors for relayMessage validation.
error InvalidRelayMessageTarget(address target);
error InvalidOriginToken(address originToken);
error InvalidDestinationChainId(uint256 destinationChainId);

// Custom errors for relayTokens validation.
error InvalidL1Token(address l1Token);
error InvalidL2Token(address l2Token);
error InvalidAmount(uint256 amount);
error InvalidTokenRecipient(address to);

/**
* @notice Constructs new Adapter.
* @param _l1Usdc USDC address on L1.
* @param _cctpTokenMessenger TokenMessenger contract to bridge tokens via CCTP.
* @param _cctpMessageTransmitter MessageTransmitter contract to bridge messages via CCTP.
* @param solanaSpokePool Solana spoke pool address, decoded from Base58 to bytes32.
* @param solanaUsdc USDC mint address on Solana, decoded from Base58 to bytes32.
* @param solanaSpokePoolUsdcVault USDC token address on Solana for the spoke pool, decoded from Base58 to bytes32.
*/
constructor(
IERC20 _l1Usdc,
ITokenMessenger _cctpTokenMessenger,
IMessageTransmitter _cctpMessageTransmitter,
bytes32 solanaSpokePool,
bytes32 solanaUsdc,
bytes32 solanaSpokePoolUsdcVault
) CircleCCTPAdapter(_l1Usdc, _cctpTokenMessenger, CircleDomainIds.Solana) {
// Solana adapter requires CCTP TokenMessenger and MessageTransmitter contracts to be set.
if (address(_cctpTokenMessenger) == address(0)) {
revert InvalidCctpTokenMessenger(address(_cctpTokenMessenger));
}
if (address(_cctpMessageTransmitter) == address(0)) {
revert InvalidCctpMessageTransmitter(address(_cctpMessageTransmitter));
}

cctpMessageTransmitter = _cctpMessageTransmitter;

SOLANA_SPOKE_POOL_BYTES32 = solanaSpokePool;
SOLANA_SPOKE_POOL_ADDRESS = solanaSpokePool.toAddressUnchecked();

SOLANA_USDC_BYTES32 = solanaUsdc;
SOLANA_USDC_ADDRESS = solanaUsdc.toAddressUnchecked();

SOLANA_SPOKE_POOL_USDC_VAULT = solanaSpokePoolUsdcVault;
}

/**
* @notice Send cross-chain message to target on Solana.
* @dev Only allows sending messages to the Solana spoke pool.
* @param target Program on Solana (translated as EVM address) that will receive message.
* @param message Data to send to target.
*/
function relayMessage(address target, bytes calldata message) external payable override {
if (target != SOLANA_SPOKE_POOL_ADDRESS) {
revert InvalidRelayMessageTarget(target);
}

bytes4 selector = bytes4(message[:4]);
if (selector == SpokePoolInterface.setEnableRoute.selector) {
Copy link
Member

Choose a reason for hiding this comment

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

Why is setEnableRoute a specific case here? Is it the only function we'll be calling on the Solana spoke pool? For example, does this prevent us from pausing deposits/fills, emergency deleting root bundles, or forcing through admin root bundles? These haven't really happened. much in the past but the latter two have happened at least once

Copy link
Contributor

Choose a reason for hiding this comment

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

We need to keep the address version of setEnableRoute for backward compatibility with the hub pool, and that specific handler translates the message to the bytes32 version.

@Reinis-FRP, do you remember why we decided to handle the translation here, which led us to do the casting here instead of handling it in SVM?

Copy link
Contributor

Choose a reason for hiding this comment

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

The main reason is that setEnableRoute is invoked via setDepositRoute on HubPool that we are not upgrading and we need different types on Solana. For other admin methods they are crafted manually and bridged via generic relaySpokePoolAdminFunction method, so the operator can adjust the interface types for all other methods to Solana.

Copy link
Contributor

@md0x md0x Nov 7, 2024

Choose a reason for hiding this comment

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

But @Reinis-FRP , couldn’t this conversion also be handled on the svm side? We initially chose to implement it here, but after thinking it over, I agree with @mrice32 that it might make more sense to handle this directly within the solana specific implementation. Also, @mrice32 pointed out a similar approach for Arbitrum in this comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

This would be bit tricky as we would need to pass mapping account that stores address translation when receiving the message on Solana side. It does not really belong under HandleReceiveMessage which translates all other supported admin calls statelessly. And if we move the address translation account down to self-invoked SetEnableRoute then we would end up changing the interface of set_enable_route to use [u8; 20] as its origin_token parameter, which is not ideal as we also support calling it from Solana admin (or need to implement both flavors). And this also requires additional admin method to update the mapping account with correct address translation.

Not saying its impossible to do, but it seemed to have less code complexity if we move the translation to the adapter on EVM side, especially, since it already needs to translate trimmed Solana USDC address to its vault associated token account anyway.

Copy link
Member

Choose a reason for hiding this comment

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

So it sounds like the tradeoff here is (less code complexity, special case for setEnableDepositRoute on the EVM side, generic SVM side logic) versus (more code complexity, but totally generic EVM logic and bespoke SVM side logic), right? What about gas costs?

cctpMessageTransmitter.sendMessage(
CircleDomainIds.Solana,
SOLANA_SPOKE_POOL_BYTES32,
_translateSetEnableRoute(message)
);
} else {
cctpMessageTransmitter.sendMessage(CircleDomainIds.Solana, SOLANA_SPOKE_POOL_BYTES32, message);
}

// TODO: consider if we need also to emit the translated message.
emit MessageRelayed(target, message);
}

/**
* @notice Bridge tokens to Solana.
* @dev Only allows bridging USDC to Solana spoke pool.
* @param l1Token L1 token to deposit.
* @param l2Token L2 token to receive.
* @param amount Amount of L1 tokens to deposit and L2 tokens to receive.
* @param to Bridge recipient.
*/
function relayTokens(
address l1Token,
address l2Token,
uint256 amount,
address to
) external payable override {
if (l1Token != address(usdcToken)) {
revert InvalidL1Token(l1Token);
}
if (l2Token != SOLANA_USDC_ADDRESS) {
revert InvalidL2Token(l2Token);
}
if (amount > type(uint64).max) {
revert InvalidAmount(amount);
}
if (to != SOLANA_SPOKE_POOL_ADDRESS) {
revert InvalidTokenRecipient(to);
}

_transferUsdc(SOLANA_SPOKE_POOL_USDC_VAULT, amount);

// TODO: consider if we need also to emit the translated addresses.
emit TokensRelayed(l1Token, l2Token, amount, to);
Copy link
Member

@nicholaspai nicholaspai Nov 6, 2024

Choose a reason for hiding this comment

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

I think it could be useful to emit the translated addresses at very little additional marginal cost

}

/**
* @notice Translates a message to enable/disable a route on Solana spoke pool.
* @param message Message to translate, expecting setEnableRoute(address,uint256,bool).
* @return Translated message, using setEnableRoute(bytes32,uint64,bool).
*/
function _translateSetEnableRoute(bytes calldata message) internal view returns (bytes memory) {
(address originToken, uint256 destinationChainId, bool enable) = abi.decode(
message[4:],
(address, uint256, bool)
);

if (originToken != SOLANA_USDC_ADDRESS) {
revert InvalidOriginToken(originToken);
}

if (destinationChainId > type(uint64).max) {
revert InvalidDestinationChainId(destinationChainId);
}

return
abi.encodeWithSignature(
"setEnableRoute(bytes32,uint64,bool)",
SOLANA_USDC_BYTES32,
uint64(destinationChainId),
enable
);
Comment on lines +182 to +188
Copy link
Contributor

Choose a reason for hiding this comment

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

OOC, why not do this mapping on the Solana side?

In theory, could we not have a mapping (from truncated address to full address) exist on the Solana side that could be modified by an admin call. Then, the flow to add a new token would require no contract changes:

  1. Send admin call to update the mapping with a new element.
  2. Add the route to use the newly added element.

Side note: this is somewhat similar to something we have to do on arbitrum.

Copy link
Contributor

Choose a reason for hiding this comment

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

We still need to map truncated USDC address to Solana spoke pool vault here to support relayTokens method used when rebalancing from HubPool to Solana spoke via CCTP token bridge. So if we were to add new token we would anyways need to redeploy the adapter, hence it is easier to keep all related aliasing contained in this contract.

}
}
42 changes: 28 additions & 14 deletions contracts/erc7683/ERC7683OrderDepositor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import { Output, GaslessCrossChainOrder, OnchainCrossChainOrder, ResolvedCrossChainOrder, IOriginSettler, FillInstruction } from "./ERC7683.sol";
import { AcrossOrderData, AcrossOriginFillerData, ERC7683Permit2Lib, ACROSS_ORDER_DATA_TYPE_HASH } from "./ERC7683Permit2Lib.sol";
import { AddressToBytes32 } from "../libraries/AddressConverters.sol";

/**
* @notice ERC7683OrderDepositor processes an external order type and translates it into an AcrossV3 deposit.
Expand All @@ -18,6 +19,7 @@ import { AcrossOrderData, AcrossOriginFillerData, ERC7683Permit2Lib, ACROSS_ORDE
*/
abstract contract ERC7683OrderDepositor is IOriginSettler {
using SafeERC20 for IERC20;
using AddressToBytes32 for address;

error WrongSettlementContract();
error WrongChainId();
Expand Down Expand Up @@ -71,6 +73,7 @@ abstract contract ERC7683OrderDepositor is IOriginSettler {
acrossOrderData.outputAmount,
acrossOrderData.destinationChainId,
acrossOriginFillerData.exclusiveRelayer,
acrossOrderData.depositNonce,
// Note: simplifying assumption to avoid quote timestamps that cause orders to expire before the deadline.
SafeCast.toUint32(order.openDeadline - QUOTE_BEFORE_DEADLINE),
order.fillDeadline,
Expand Down Expand Up @@ -101,6 +104,7 @@ abstract contract ERC7683OrderDepositor is IOriginSettler {
acrossOrderData.outputAmount,
acrossOrderData.destinationChainId,
acrossOrderData.exclusiveRelayer,
acrossOrderData.depositNonce,
// Note: simplifying assumption to avoid the order type having to bake in the quote timestamp.
SafeCast.toUint32(block.timestamp),
order.fillDeadline,
Expand Down Expand Up @@ -159,6 +163,17 @@ abstract contract ERC7683OrderDepositor is IOriginSettler {
return SafeCast.toUint32(block.timestamp); // solhint-disable-line not-rely-on-time
}

/**
* @notice Convenience method to compute the Across depositId for orders sent through 7683.
* @dev if a 0 depositNonce is used, the depositId will not be deterministic (meaning it can change depending on
* when the open txn is mined), but you will be safe from collisions. See the unsafeDepositV3 method on SpokePool
* for more details on how to choose between deterministic and non-deterministic.
* @param depositNonce the depositNonce field in the order.
* @param depositor the sender or signer of the order.
* @return the resulting Across depositId.
*/
function computeDepositId(uint256 depositNonce, address depositor) public view virtual returns (uint256);

function _resolveFor(GaslessCrossChainOrder calldata order, bytes calldata fillerData)
internal
view
Expand Down Expand Up @@ -213,15 +228,15 @@ abstract contract ERC7683OrderDepositor is IOriginSettler {

FillInstruction[] memory fillInstructions = new FillInstruction[](1);
V3SpokePoolInterface.V3RelayData memory relayData;
relayData.depositor = order.user;
relayData.recipient = _toAddress(acrossOrderData.recipient);
relayData.exclusiveRelayer = acrossOriginFillerData.exclusiveRelayer;
relayData.inputToken = acrossOrderData.inputToken;
relayData.outputToken = acrossOrderData.outputToken;
relayData.depositor = order.user.toBytes32();
relayData.recipient = acrossOrderData.recipient;
relayData.exclusiveRelayer = acrossOriginFillerData.exclusiveRelayer.toBytes32();
relayData.inputToken = acrossOrderData.inputToken.toBytes32();
relayData.outputToken = acrossOrderData.outputToken.toBytes32();
relayData.inputAmount = acrossOrderData.inputAmount;
relayData.outputAmount = acrossOrderData.outputAmount;
relayData.originChainId = block.chainid;
relayData.depositId = _currentDepositId();
relayData.depositId = computeDepositId(acrossOrderData.depositNonce, order.user);
relayData.fillDeadline = order.fillDeadline;
relayData.exclusivityDeadline = acrossOrderData.exclusivityPeriod;
relayData.message = acrossOrderData.message;
Expand Down Expand Up @@ -277,15 +292,15 @@ abstract contract ERC7683OrderDepositor is IOriginSettler {

FillInstruction[] memory fillInstructions = new FillInstruction[](1);
V3SpokePoolInterface.V3RelayData memory relayData;
relayData.depositor = msg.sender;
relayData.recipient = _toAddress(acrossOrderData.recipient);
relayData.exclusiveRelayer = acrossOrderData.exclusiveRelayer;
relayData.inputToken = acrossOrderData.inputToken;
relayData.outputToken = acrossOrderData.outputToken;
relayData.depositor = msg.sender.toBytes32();
relayData.recipient = acrossOrderData.recipient;
relayData.exclusiveRelayer = acrossOrderData.exclusiveRelayer.toBytes32();
relayData.inputToken = acrossOrderData.inputToken.toBytes32();
relayData.outputToken = acrossOrderData.outputToken.toBytes32();
relayData.inputAmount = acrossOrderData.inputAmount;
relayData.outputAmount = acrossOrderData.outputAmount;
relayData.originChainId = block.chainid;
relayData.depositId = _currentDepositId();
relayData.depositId = computeDepositId(acrossOrderData.depositNonce, msg.sender);
relayData.fillDeadline = order.fillDeadline;
relayData.exclusivityDeadline = acrossOrderData.exclusivityPeriod;
relayData.message = acrossOrderData.message;
Expand Down Expand Up @@ -355,13 +370,12 @@ abstract contract ERC7683OrderDepositor is IOriginSettler {
uint256 outputAmount,
uint256 destinationChainId,
address exclusiveRelayer,
uint256 depositNonce,
uint32 quoteTimestamp,
uint32 fillDeadline,
uint32 exclusivityPeriod,
bytes memory message
) internal virtual;

function _currentDepositId() internal view virtual returns (uint32);

function _destinationSettler(uint256 chainId) internal view virtual returns (address);
}
Loading
Loading