Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 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
3e34e74
WIP
chrismaree Nov 4, 2024
268af70
Merge branch 'master' into chrismaree/standardize-errors
chrismaree Nov 4, 2024
dd88eac
WIP
chrismaree Nov 4, 2024
a3df3c1
WIP
chrismaree Nov 4, 2024
f3f0c76
WIP
chrismaree Nov 4, 2024
162ce53
WIP
chrismaree Nov 4, 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
c4cef8c
Merge branch 'svm-dev' into chrismaree/standardize-errors
chrismaree Nov 19, 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
bb87650
Merge branch 'svm-dev' into chrismaree/standardize-errors
chrismaree Nov 21, 2024
e891bd7
WIP
chrismaree Nov 21, 2024
dea0592
WIP
chrismaree Nov 21, 2024
088614c
WIP
chrismaree Nov 21, 2024
c3e8b5f
WIP
chrismaree Nov 22, 2024
4243dc0
WIP
chrismaree Nov 22, 2024
178433b
Discard changes to Anchor.toml
chrismaree Nov 22, 2024
e8fa2cb
Discard changes to contracts/Linea_SpokePool.sol
chrismaree Nov 22, 2024
6ad38cf
Discard changes to contracts/Ovm_SpokePool.sol
chrismaree Nov 22, 2024
c5bc40d
Discard changes to contracts/PolygonZkEVM_SpokePool.sol
chrismaree Nov 22, 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
7 changes: 3 additions & 4 deletions contracts/Polygon_SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ contract Polygon_SpokePool is IFxMessageProcessor, SpokePool, CircleCCTPAdapter
* @param data ABI encoded function call to execute on this contract.
*/
function processMessageFromRoot(
uint256, /*stateId*/
uint256,
/*stateId*/
address rootMessageSender,
bytes calldata data
) public validateInternalCalls {
Expand Down Expand Up @@ -203,7 +204,6 @@ contract Polygon_SpokePool is IFxMessageProcessor, SpokePool, CircleCCTPAdapter
* whereby someone batches this call with a bunch of other calls and produces a very large L2 burn transaction.
* This might make the L2 -> L1 message fail due to exceeding the L1 calldata limit.
*/

function executeRelayerRefundLeaf(
uint32 rootBundleId,
SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,
Expand All @@ -220,7 +220,6 @@ contract Polygon_SpokePool is IFxMessageProcessor, SpokePool, CircleCCTPAdapter
/**************************************
* INTERNAL FUNCTIONS *
**************************************/

function _setFxChild(address _fxChild) internal {
//slither-disable-next-line missing-zero-check
fxChild = _fxChild;
Expand All @@ -232,7 +231,7 @@ contract Polygon_SpokePool is IFxMessageProcessor, SpokePool, CircleCCTPAdapter
emit SetPolygonTokenBridger(address(_polygonTokenBridger));
}

function _preExecuteLeafHook(address) internal override {
function _preExecuteLeafHook(bytes32) internal override {
// Wraps MATIC --> WMATIC before distributing tokens from this contract.
_wrap();
}
Expand Down
429 changes: 351 additions & 78 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
47 changes: 26 additions & 21 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 { Bytes32ToAddress } from "./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 Bytes32ToAddress for bytes32;

// 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 All @@ -37,19 +39,19 @@ abstract contract SwapAndBridgeBase is Lockable, MultiCaller {
// until after the swap.
struct DepositData {
// Token received on destination chain.
address outputToken;
bytes32 outputToken;
// Amount of output token to be received by recipient.
uint256 outputAmount;
// The account credited with deposit who can submit speedups to the Across deposit.
address depositor;
bytes32 depositor;
// The account that will receive the output token on the destination chain. If the output token is
// wrapped native token, then if this is an EOA then they will receive native token on the destination
// chain and if this is a contract then they will receive an ERC20.
address recipient;
bytes32 recipient;
// The destination chain identifier.
uint256 destinationChainid;
// The account that can exclusively fill the deposit before the exclusivity deadline.
address exclusiveRelayer;
bytes32 exclusiveRelayer;
// Timestamp of the deposit used by system to charge fees. Must be within short window of time into the past
// relative to this chain's current time or deposit will revert.
uint32 quoteTimestamp;
Expand All @@ -63,11 +65,11 @@ abstract contract SwapAndBridgeBase is Lockable, MultiCaller {

event SwapBeforeBridge(
address exchange,
address indexed swapToken,
address indexed acrossInputToken,
bytes32 indexed swapToken,
bytes32 indexed acrossInputToken,
uint256 swapTokenAmount,
uint256 acrossInputAmount,
address indexed acrossOutputToken,
bytes32 indexed acrossOutputToken,
uint256 acrossOutputAmount
);

Expand Down Expand Up @@ -104,17 +106,17 @@ abstract contract SwapAndBridgeBase is Lockable, MultiCaller {
uint256 swapTokenAmount,
uint256 minExpectedInputTokenAmount,
DepositData calldata depositData,
IERC20 _swapToken,
IERC20 _acrossInputToken
bytes32 _swapToken,
bytes32 _acrossInputToken
) internal {
// Note: this check should never be impactful, but is here out of an abundance of caution.
// For example, if the exchange address in the contract is also an ERC20 token that is approved by some
// user on this contract, a malicious actor could call transferFrom to steal the user's tokens.
if (!allowedSelectors[bytes4(routerCalldata)]) revert InvalidFunctionSelector();

// Swap and run safety checks.
uint256 srcBalanceBefore = _swapToken.balanceOf(address(this));
uint256 dstBalanceBefore = _acrossInputToken.balanceOf(address(this));
uint256 srcBalanceBefore = IERC20(_swapToken.toAddress()).balanceOf(address(this));
uint256 dstBalanceBefore = IERC20(_acrossInputToken.toAddress()).balanceOf(address(this));

_swapToken.safeIncreaseAllowance(exchange, swapTokenAmount);
// solhint-disable-next-line avoid-low-level-calls
Expand All @@ -138,23 +140,26 @@ abstract contract SwapAndBridgeBase is Lockable, MultiCaller {
* @param swapTokenBalanceBefore Balance of swapToken before swap.
* @param inputTokenBalanceBefore Amount of Across input token we held before swap
* @param minExpectedInputTokenAmount Minimum amount of received acrossInputToken that we'll bridge
**/
*
*/
function _checkSwapOutputAndDeposit(
uint256 swapTokenAmount,
uint256 swapTokenBalanceBefore,
uint256 inputTokenBalanceBefore,
uint256 minExpectedInputTokenAmount,
DepositData calldata depositData,
IERC20 _swapToken,
IERC20 _acrossInputToken
bytes32 _swapToken,
bytes32 _acrossInputToken
) internal {
// Sanity check that we received as many tokens as we require:
uint256 returnAmount = _acrossInputToken.balanceOf(address(this)) - inputTokenBalanceBefore;
uint256 returnAmount = IERC20(_acrossInputToken.toAddress()).balanceOf(address(this)) - inputTokenBalanceBefore;
// Sanity check that received amount from swap is enough to submit Across deposit with.
if (returnAmount < minExpectedInputTokenAmount) revert MinimumExpectedInputAmount();
// Sanity check that we don't have any leftover swap tokens that would be locked in this contract (i.e. check
// that we weren't partial filled).
if (swapTokenBalanceBefore - _swapToken.balanceOf(address(this)) != swapTokenAmount) revert LeftoverSrcTokens();
if (swapTokenBalanceBefore - IERC20(_swapToken.toAddress()).balanceOf(address(this)) != swapTokenAmount) {
revert LeftoverSrcTokens();
}

emit SwapBeforeBridge(
exchange,
Expand Down Expand Up @@ -184,7 +189,7 @@ abstract contract SwapAndBridgeBase is Lockable, MultiCaller {
spokePool.depositV3(
depositData.depositor,
depositData.recipient,
address(_acrossInputToken), // input token
_acrossInputToken, // input token
depositData.outputToken, // output token
_acrossInputAmount, // input amount.
depositData.outputAmount, // output amount
Expand All @@ -210,10 +215,10 @@ contract SwapAndBridge is SwapAndBridgeBase {
// This contract simply enables the caller to swap a token on this chain for another specified one
// and bridge it as the input token via Across. This simplification is made to make the code
// easier to reason about and solve a specific use case for Across.
IERC20 public immutable SWAP_TOKEN;
bytes32 public immutable SWAP_TOKEN;

// The token that will be bridged via Across as the inputToken.
IERC20 public immutable ACROSS_INPUT_TOKEN;
bytes32 public immutable ACROSS_INPUT_TOKEN;

/**
* @notice Construct a new SwapAndBridge contract.
Expand Down Expand Up @@ -303,8 +308,8 @@ contract UniversalSwapAndBridge is SwapAndBridgeBase {
* @param depositData Specifies the Across deposit params we'll send after the swap.
*/
function swapAndBridge(
IERC20 swapToken,
IERC20 acrossInputToken,
bytes32 swapToken,
bytes32 acrossInputToken,
bytes calldata routerCalldata,
uint256 swapTokenAmount,
uint256 minExpectedInputTokenAmount,
Expand Down
5 changes: 3 additions & 2 deletions contracts/ZkSync_SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface IL2ETH {
* @custom:security-contact bugs@across.to
*/
contract ZkSync_SpokePool is SpokePool {
using AddressToBytes32 for address;
// On Ethereum, avoiding constructor parameters and putting them into constants reduces some of the gas cost
// upon contract deployment. On zkSync the opposite is true: deploying the same bytecode for contracts,
// while changing only constructor parameters can lead to substantial fee savings. So, the following params
Expand Down Expand Up @@ -88,8 +89,8 @@ contract ZkSync_SpokePool is SpokePool {
* @notice Wraps any ETH into WETH before executing base function. This is necessary because SpokePool receives
* ETH over the canonical token bridge instead of WETH.
*/
function _preExecuteLeafHook(address l2TokenAddress) internal override {
if (l2TokenAddress == address(wrappedNativeToken)) _depositEthToWeth();
function _preExecuteLeafHook(bytes32 l2TokenAddress) internal override {
if (l2TokenAddress == address(wrappedNativeToken).toBytes32()) _depositEthToWeth();
}

// Wrap any ETH owned by this contract so we can send expected L2 token to recipient. This is necessary because
Expand Down
Loading
Loading