Skip to content

Commit

Permalink
Merge branch 'master' into npai/custom-gas-token-precision
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholaspai authored Sep 11, 2024
2 parents 54fef94 + a858f4b commit 6e7f30b
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 33 deletions.
9 changes: 7 additions & 2 deletions contracts/SpokePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,11 @@ abstract contract SpokePool is
********************************************/

/**
* @notice Previously, this function allowed the caller to specify the exclusivityDeadline, otherwise known as the
* as exact timestamp on the destination chain before which only the exclusiveRelayer could fill the deposit. Now,
* the caller is expected to pass in an exclusivityPeriod which is the number of seconds to be added to the
* block.timestamp to produce the exclusivityDeadline. This allows the caller to ignore any latency associated
* with this transaction being mined and propagating this transaction to the miner.
* @notice Request to bridge input token cross chain to a destination chain and receive a specified amount
* of output tokens. The fee paid to relayers and the system should be captured in the spread between output
* amount and input amount when adjusted to be denominated in the input token. A relayer on the destination
Expand Down Expand Up @@ -523,7 +528,7 @@ abstract contract SpokePool is
* @param fillDeadline The deadline for the relayer to fill the deposit. After this destination chain timestamp,
* the fill will revert on the destination chain. Must be set between [currentTime, currentTime + fillDeadlineBuffer]
* where currentTime is block.timestamp on this chain or this transaction will revert.
* @param exclusivityPeriod Added to the current time to set the exclusive reayer deadline,
* @param exclusivityPeriod Added to the current time to set the exclusive relayer deadline,
* which is the deadline for the exclusiveRelayer to fill the deposit. After this destination chain timestamp,
* anyone can fill the deposit.
* @param message The message to send to the recipient on the destination chain if the recipient is a contract.
Expand Down Expand Up @@ -592,7 +597,7 @@ abstract contract SpokePool is
numberOfDeposits++,
quoteTimestamp,
fillDeadline,
uint32(getCurrentTime()) + exclusivityPeriod,
uint32(currentTime) + exclusivityPeriod,
depositor,
recipient,
exclusiveRelayer,
Expand Down
1 change: 1 addition & 0 deletions contracts/chain-adapters/Arbitrum_Adapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ contract Arbitrum_Adapter is AdapterInterface, CircleCCTPAdapter {

/**
* @notice Returns required amount of ETH to send a message via the Inbox.
* @param l2GasLimit L2 gas limit for the message.
* @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.
*/
function getL1CallValue(uint32 l2GasLimit) public pure returns (uint256) {
Expand Down
32 changes: 20 additions & 12 deletions contracts/chain-adapters/Arbitrum_CustomGasToken_Adapter.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import "./interfaces/AdapterInterface.sol";
import { AdapterInterface } from "./interfaces/AdapterInterface.sol";

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../external/interfaces/CCTPInterfaces.sol";
import "../libraries/CircleCCTPAdapter.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ITokenMessenger as ICCTPTokenMessenger } from "../external/interfaces/CCTPInterfaces.sol";
import { CircleCCTPAdapter, CircleDomainIds } from "../libraries/CircleCCTPAdapter.sol";

interface FunderInterface {
function withdraw(IERC20 token, uint256 amount) external;
Expand All @@ -28,6 +28,7 @@ interface ArbitrumL1ERC20Bridge {
/**
* @notice Returns token that is escrowed in bridge on L1 side and minted on L2 as native currency.
* @dev This function doesn't exist on the generic Bridge interface.
* @return address of the native token.
*/
function nativeToken() external view returns (address);

Expand All @@ -48,6 +49,7 @@ interface ArbitrumL1InboxLike {
/**
* @dev we only use this function to check the native token used by the bridge, so we hardcode the interface
* to return an ArbitrumL1ERC20Bridge instead of a more generic Bridge interface.
* @return address of the bridge.
*/
function bridge() external view returns (ArbitrumL1ERC20Bridge);

Expand Down Expand Up @@ -128,9 +130,9 @@ interface ArbitrumL1ERC20GatewayLike {
* 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 its only necessary that the HubPool's methods
* that call this contract's logic guard against reentrancy.
* @dev This contract is very similar to Arbitrum_Adapter but it allows the caller to pay for submission
* fees using a custom gas token. This is required to support certain Arbitrum orbit L2s and L3s.
* @dev This contract
* @dev This contract is very similar to Arbitrum_Adapter but it allows the caller to pay for retryable ticket
* submission fees using a custom gas token. This is required to support certain Arbitrum orbit L2s and L3s.
* @custom:security-contact [email protected]
*/

// solhint-disable-next-line contract-name-camelcase
Expand Down Expand Up @@ -166,6 +168,9 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter

FunderInterface public immutable CUSTOM_GAS_TOKEN_FUNDER;

Check warning on line 169 in contracts/chain-adapters/Arbitrum_CustomGasToken_Adapter.sol

View workflow job for this annotation

GitHub Actions / Solhint (16)

Variable name must be in mixedCase

Check warning on line 169 in contracts/chain-adapters/Arbitrum_CustomGasToken_Adapter.sol

View workflow job for this annotation

GitHub Actions / Solhint (16)

Variable name must be in mixedCase

error InvalidCustomGasToken();
error InsufficientCustomGasToken();

/**
* @notice Constructs new Adapter.
* @param _l1ArbitrumInbox Inbox helper contract to send messages to Arbitrum.
Expand All @@ -176,13 +181,16 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter
* @param _l2GasPrice Gas price bid for L2 execution. Should be set conservatively high to avoid stuck messages.
* @param _cctpTokenMessenger TokenMessenger contract to bridge via CCTP.
* @param _customGasTokenFunder Contract that funds the custom gas token.
* @param _l2MaxSubmissionCost Amount of gas token allocated to pay for the base submission fee. The base
* submission fee is a parameter unique to Arbitrum retryable transactions. This value is hardcoded
* and used for all messages sent by this adapter.
*/
constructor(
ArbitrumL1InboxLike _l1ArbitrumInbox,
ArbitrumL1ERC20GatewayLike _l1ERC20GatewayRouter,
address _l2RefundL2Address,
IERC20 _l1Usdc,
ITokenMessenger _cctpTokenMessenger,
ICCTPTokenMessenger _cctpTokenMessenger,
FunderInterface _customGasTokenFunder,
uint256 _l2MaxSubmissionCost,
uint256 _l2GasPrice
Expand All @@ -191,8 +199,7 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter
L1_ERC20_GATEWAY_ROUTER = _l1ERC20GatewayRouter;
L2_REFUND_L2_ADDRESS = _l2RefundL2Address;
CUSTOM_GAS_TOKEN = IERC20(L1_INBOX.bridge().nativeToken());
require(L1_INBOX.bridge().nativeTokenDecimals() <= 18, "Invalid precision");
require(address(CUSTOM_GAS_TOKEN) != address(0), "Invalid custom gas token");
if (address(CUSTOM_GAS_TOKEN) == address(0)) revert InvalidCustomGasToken();
L2_MAX_SUBMISSION_COST = _l2MaxSubmissionCost;
L2_GAS_PRICE = _l2GasPrice;
CUSTOM_GAS_TOKEN_FUNDER = _customGasTokenFunder;
Expand Down Expand Up @@ -291,6 +298,7 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter
/**
* @notice Returns required amount of gas token to send a message via the Inbox.
* @dev Should return a value in the same precision as the gas token's precision.
* @param l2GasLimit L2 gas limit for the message.
* @return amount of gas token that this contract needs to hold in order for relayMessage to succeed.
*/
function getL1CallValue(uint32 l2GasLimit) public view returns (uint256) {
Expand All @@ -300,7 +308,7 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter
function _pullCustomGas(uint32 l2GasLimit) internal returns (uint256) {
uint256 requiredL1CallValue = getL1CallValue(l2GasLimit);
CUSTOM_GAS_TOKEN_FUNDER.withdraw(CUSTOM_GAS_TOKEN, requiredL1CallValue);
require(CUSTOM_GAS_TOKEN.balanceOf(address(this)) >= requiredL1CallValue, "Insufficient gas balance");
if (CUSTOM_GAS_TOKEN.balanceOf(address(this)) < requiredL1CallValue) revert InsufficientCustomGasToken();
return requiredL1CallValue;
}

Expand Down
19 changes: 0 additions & 19 deletions contracts/chain-adapters/Arbitrum_CustomGasToken_Funder.sol

This file was deleted.

30 changes: 30 additions & 0 deletions contracts/chain-adapters/DonationBox.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

/**
* @notice Users can donate tokens to this contract that only the owner can withdraw.
* @dev This contract is designed to be used as a convience for the owner to store funds to pay for
* future transactions, such as donating custom gas tokens to pay for future retryable ticket messages
* to be sent via the Arbitrum_Adapter.
* @custom:security-contact [email protected]
*/
contract DonationBox is Ownable {
using SafeERC20 for IERC20;

/**
* @notice Withdraw tokens from the contract.
* @dev Only callable by owner, which should be set to the HubPool
* so that it can use these funds to pay for relaying messages to
* an Arbitrum L2 that uses custom gas tokens as the L1 payment currency,
* via the Arbitrum_CustomGasToken_Adapter.
* @param token Token to withdraw.
* @param amount Amount of tokens to withdraw.
*/
function withdraw(IERC20 token, uint256 amount) external onlyOwner {
token.safeTransfer(msg.sender, amount);
}
}
5 changes: 5 additions & 0 deletions deployments/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Across Mainnet Deployment Addresses

All of the SpokePool addresses listed here are [upgradeable proxy](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/2d081f24cac1a867f6f73d512f2022e1fa987854/contracts/proxy/utils/UUPSUpgradeable.sol) contract addresses. If you want to get implementation contract information (ABI, bytecode, addresses) then go to the relevant folder in this directory for the contract and chain you are looking for. You can read more about the proxy upgradeability pattern we use [here](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/2d081f24cac1a867f6f73d512f2022e1fa987854/contracts/proxy/README.adoc)

The [`deployments.json`](./deployments.json) file also maintains the most up to date **proxy (i.e.not implementation)** addresses and you should view it as the source of truth in case it differs from this `README`.
This is because this `deployments.json` file is used by bots in [`@across-protocol/relayer`](https://github.com/across-protocol/relayer) and [`@across-protocol/sdk`](https://github.com/across-protocol/sdk) to programmatically load the latest contract addresses. This `README` is not a dependency in those repositories so it is more likely to be out of sync with the latest addresses.

## Mainnet (1)

| Contract Name | Address |
Expand Down

0 comments on commit 6e7f30b

Please sign in to comment.