Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 1 addition & 1 deletion contracts/Arbitrum_SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// Arbitrum only supports v0.8.19
// See https://docs.arbitrum.io/for-devs/concepts/differences-between-arbitrum-ethereum/solidity-support#differences-from-solidity-on-ethereum
pragma solidity 0.8.19;
pragma solidity ^0.8.19;

import "./SpokePool.sol";
import "./libraries/CircleCCTPAdapter.sol";
Expand Down
2 changes: 1 addition & 1 deletion contracts/Linea_SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// Linea only support v0.8.19
// See https://docs.linea.build/build-on-linea/ethereum-differences#evm-opcodes
pragma solidity 0.8.19;
pragma solidity ^0.8.19;

import "./SpokePool.sol";
import { IMessageService, ITokenBridge, IUSDCBridge } from "./external/interfaces/LineaInterfaces.sol";
Expand Down
96 changes: 96 additions & 0 deletions contracts/erc7683/ERC7683.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;

/// @notice Tokens sent by the swapper as inputs to the order
struct Input {
/// @dev The address of the ERC20 token on the origin chain
address token;
/// @dev The amount of the token to be sent
uint256 amount;
}

/// @notice Tokens that must be receive for a valid order fulfillment
struct Output {
/// @dev The address of the ERC20 token on the destination chain
/// @dev address(0) used as a sentinel for the native token
address token;
/// @dev The amount of the token to be sent
uint256 amount;
/// @dev The address to receive the output tokens
address recipient;
/// @dev The destination chain for this output
uint32 chainId;
}

/// @title CrossChainOrder type
/// @notice Standard order struct to be signed by swappers, disseminated to fillers, and submitted to settlement contracts
struct CrossChainOrder {
/// @dev The contract address that the order is meant to be settled by.
/// Fillers send this order to this contract address on the origin chain
address settlementContract;
/// @dev The address of the user who is initiating the swap,
/// whose input tokens will be taken and escrowed
address swapper;
/// @dev Nonce to be used as replay protection for the order
uint256 nonce;
/// @dev The chainId of the origin chain
uint32 originChainId;
/// @dev The timestamp by which the order must be initiated
uint32 initiateDeadline;
/// @dev The timestamp by which the order must be filled on the destination chain
uint32 fillDeadline;
/// @dev Arbitrary implementation-specific data
/// Can be used to define tokens, amounts, destination chains, fees, settlement parameters,
/// or any other order-type specific information
bytes orderData;
}

/// @title ResolvedCrossChainOrder type
/// @notice An implementation-generic representation of an order
/// @dev Defines all requirements for filling an order by unbundling the implementation-specific orderData.
/// @dev Intended to improve integration generalization by allowing fillers to compute the exact input and output information of any order
struct ResolvedCrossChainOrder {
/// @dev The contract address that the order is meant to be settled by.
address settlementContract;
/// @dev The address of the user who is initiating the swap
address swapper;
/// @dev Nonce to be used as replay protection for the order
uint256 nonce;
/// @dev The chainId of the origin chain
uint32 originChainId;
/// @dev The timestamp by which the order must be initiated
uint32 initiateDeadline;
/// @dev The timestamp by which the order must be filled on the destination chain(s)
uint32 fillDeadline;
/// @dev The inputs to be taken from the swapper as part of order initiation
Input[] swapperInputs;
/// @dev The outputs to be given to the swapper as part of order fulfillment
Output[] swapperOutputs;
/// @dev The outputs to be given to the filler as part of order settlement
Output[] fillerOutputs;
}

/// @title ISettlementContract
/// @notice Standard interface for settlement contracts
interface ISettlementContract {
Copy link
Member Author

Choose a reason for hiding this comment

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

should this file be named IERC7683.sol?

/// @notice Initiates the settlement of a cross-chain order
/// @dev To be called by the filler
/// @param order The CrossChainOrder definition
/// @param signature The swapper's signature over the order
/// @param fillerData Any filler-defined data required by the settler
function initiate(
CrossChainOrder memory order,
bytes memory signature,
bytes memory fillerData
) external;

/// @notice Resolves a specific CrossChainOrder into a generic ResolvedCrossChainOrder
/// @dev Intended to improve standardized integration of various order types and settlement contracts
/// @param order The CrossChainOrder definition
/// @param fillerData Any filler-defined data required by the settler
/// @return ResolvedCrossChainOrder hydrated order data including the inputs and outputs of the order
function resolve(CrossChainOrder memory order, bytes memory fillerData)
external
view
returns (ResolvedCrossChainOrder memory);
}
93 changes: 93 additions & 0 deletions contracts/erc7683/ERC7683Across.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "../external/interfaces/IPermit2.sol";
import { CrossChainOrder } from "./ERC7683.sol";

// Data unique to every CrossChainOrder settled on Across
struct AcrossOrderData {
address inputToken;
uint256 inputAmount;
address outputToken;
uint256 outputAmount;
uint32 destinationChainId;
address recipient;
uint32 exclusivityDeadline;
bytes message;
}

struct AcrossFillerData {
address exclusiveRelayer;
}

/**
* @notice ERC7683Permit2Lib knows how to process a particular type of external Permit2Order so that it can be used in Across.
* @dev This library is responsible for definining the ERC712 type strings/hashes and performing hashes on the types.
*/
library ERC7683Permit2Lib {
bytes private constant ACROSS_ORDER_DATA_TYPE =
abi.encodePacked(
"AcrossOrderData(",
"address inputToken,",
"uint256 inputAmount,",
"address outputToken,",
"uint256 outputAmount,",
"uint32 destinationChainId,",
"address recipient,",
"uint32 exclusivityDeadline,",
"bytes message)"
);

bytes32 private constant ACROSS_ORDER_DATA_TYPE_HASH = keccak256(ACROSS_ORDER_DATA_TYPE);

bytes internal constant CROSS_CHAIN_ORDER_TYPE =
abi.encodePacked(
"CrossChainOrder(",
"address settlerContract,",
"address swapper,",
"uint256 nonce,",
"uint32 originChainId,",
"uint32 initiateDeadline,",
"uint32 fillDeadline,",
"AcrossOrderData orderData)",
ACROSS_ORDER_DATA_TYPE
);
bytes32 internal constant CROSS_CHAIN_ORDER_TYPE_HASH = keccak256(CROSS_CHAIN_ORDER_TYPE);
string private constant TOKEN_PERMISSIONS_TYPE = "TokenPermissions(address token,uint256 amount)";
string internal constant PERMIT2_ORDER_TYPE =
string(abi.encodePacked("CrossChainOrder witness)", CROSS_CHAIN_ORDER_TYPE, TOKEN_PERMISSIONS_TYPE));

// Hashes an order to get an order hash. Needed for permit2.
function hashOrder(CrossChainOrder memory order, bytes32 orderDataHash) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
CROSS_CHAIN_ORDER_TYPE_HASH,
order.settlementContract,
order.swapper,
order.nonce,
order.originChainId,
order.initiateDeadline,
order.fillDeadline,
orderDataHash
)
);
}

function hashOrderData(AcrossOrderData memory orderData) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
ACROSS_ORDER_DATA_TYPE_HASH,
orderData.inputToken,
orderData.inputAmount,
orderData.outputToken,
orderData.outputAmount,
orderData.destinationChainId,
orderData.recipient,
orderData.exclusivityDeadline,
orderData.message
)
);
}
}
Loading