diff --git a/contracts/chain-adapters/Arbitrum_CustomGasToken_Adapter.sol b/contracts/chain-adapters/Arbitrum_CustomGasToken_Adapter.sol index 9a876cc9..c6b052da 100644 --- a/contracts/chain-adapters/Arbitrum_CustomGasToken_Adapter.sol +++ b/contracts/chain-adapters/Arbitrum_CustomGasToken_Adapter.sol @@ -51,9 +51,9 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter // The Arbitrum Inbox requires that this is specified in gWei (e.g. 1e9 = 1 gWei) uint256 public immutable L2_GAS_PRICE; - // Native token expected to be sent in L2 message. Should be 0 for all use cases of this constant, which - // includes sending messages from L1 to L2 and sending Custom gas token ERC20's, which won't be the native token - // on the L2 by definition. + // Native token expected to be sent in L2 message. Should be 0 for most use cases of this constant. This + // constant is unused when sending the native gas token over the inbox since the inbox interprets `l2CallValue` + // as the amount of the L2 native token to send. uint256 public constant L2_CALL_VALUE = 0; // Gas limit for L2 execution of a cross chain token transfer sent via the inbox. @@ -61,6 +61,10 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter // Gas limit for L2 execution of a message sent via the inbox. uint32 public constant RELAY_MESSAGE_L2_GAS_LIMIT = 2_000_000; + // The number of decimals of precision for the custom gas token. This is defined in the constructor and not dynamically fetched since decimals are + // not part of the standard ERC20 interface. + uint8 public immutable NATIVE_TOKEN_DECIMALS; + // This address on L2 receives extra gas token that is left over after relaying a message via the inbox. address public immutable L2_REFUND_L2_ADDRESS; @@ -104,10 +108,12 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter address _l2RefundL2Address, IERC20 _l1Usdc, ICCTPTokenMessenger _cctpTokenMessenger, + uint32 _circleDomainId, FunderInterface _customGasTokenFunder, + uint8 _nativeTokenDecimals, uint256 _l2MaxSubmissionCost, uint256 _l2GasPrice - ) CircleCCTPAdapter(_l1Usdc, _cctpTokenMessenger, CircleDomainIds.Arbitrum) { + ) CircleCCTPAdapter(_l1Usdc, _cctpTokenMessenger, _circleDomainId) { L1_INBOX = _l1ArbitrumInbox; L1_ERC20_GATEWAY_ROUTER = _l1ERC20GatewayRouter; L2_REFUND_L2_ADDRESS = _l2RefundL2Address; @@ -116,6 +122,7 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter L2_MAX_SUBMISSION_COST = _l2MaxSubmissionCost; L2_GAS_PRICE = _l2GasPrice; CUSTOM_GAS_TOKEN_FUNDER = _customGasTokenFunder; + NATIVE_TOKEN_DECIMALS = _nativeTokenDecimals; } /** @@ -177,7 +184,7 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter CUSTOM_GAS_TOKEN.safeIncreaseAllowance(address(L1_INBOX), amountToBridge); L1_INBOX.createRetryableTicket( to, // destAddr destination L2 contract address - L2_CALL_VALUE, // l2CallValue call value for retryable L2 message + amount, // l2CallValue call value for retryable L2 message L2_MAX_SUBMISSION_COST, // maxSubmissionCost Max gas deducted from user's L2 balance to cover base fee L2_REFUND_L2_ADDRESS, // excessFeeRefundAddress maxgas * gasprice - execution cost gets credited here on L2 L2_REFUND_L2_ADDRESS, // callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled @@ -226,12 +233,11 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter } function _from18ToNativeDecimals(uint256 amount) internal view returns (uint256) { - uint8 nativeTokenDecimals = L1_INBOX.bridge().nativeTokenDecimals(); - if (nativeTokenDecimals == 18) { + if (NATIVE_TOKEN_DECIMALS == 18) { return amount; - } else if (nativeTokenDecimals < 18) { + } else if (NATIVE_TOKEN_DECIMALS < 18) { // Round up the division result so that the L1 call value is always sufficient to cover the submission fee. - uint256 reductionFactor = 10**(18 - nativeTokenDecimals); + uint256 reductionFactor = 10**(18 - NATIVE_TOKEN_DECIMALS); uint256 divFloor = amount / reductionFactor; uint256 mod = amount % reductionFactor; if (mod != 0) { @@ -240,7 +246,7 @@ contract Arbitrum_CustomGasToken_Adapter is AdapterInterface, CircleCCTPAdapter return divFloor; } } else { - return amount * 10**(nativeTokenDecimals - 18); + return amount * 10**(NATIVE_TOKEN_DECIMALS - 18); } } } diff --git a/deploy/052_deploy_donation_box.ts b/deploy/052_deploy_donation_box.ts new file mode 100644 index 00000000..4e2a5f21 --- /dev/null +++ b/deploy/052_deploy_donation_box.ts @@ -0,0 +1,16 @@ +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployer } = await hre.getNamedAccounts(); + + await hre.deployments.deploy("DonationBox", { + contract: "DonationBox", + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + args: [], + }); +}; +module.exports = func; +func.tags = ["DonationBox"]; diff --git a/deploy/053_deploy_alephzero_adapter.ts b/deploy/053_deploy_alephzero_adapter.ts new file mode 100644 index 00000000..5bfc157d --- /dev/null +++ b/deploy/053_deploy_alephzero_adapter.ts @@ -0,0 +1,35 @@ +import { L1_ADDRESS_MAP, ZERO_ADDRESS, AZERO, ARBITRUM_MAX_SUBMISSION_COST, AZERO_GAS_PRICE } from "./consts"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployer } = await hre.getNamedAccounts(); + const chainId = parseInt(await hre.getChainId()); + + // This address receives gas refunds on the L2 after messages are relayed. Currently + // set to the Risk Labs relayer address. The deployer should change this if necessary. + const l2RefundAddress = "0x07aE8551Be970cB1cCa11Dd7a11F47Ae82e70E67"; + + const args = [ + L1_ADDRESS_MAP[chainId].l1AlephZeroInbox, + L1_ADDRESS_MAP[chainId].l1AlephZeroERC20GatewayRouter, + l2RefundAddress, + ZERO_ADDRESS, + ZERO_ADDRESS, + 0, // No Circle CCTP domain ID. + L1_ADDRESS_MAP[chainId].donationBox, + AZERO.decimals, + ARBITRUM_MAX_SUBMISSION_COST, + AZERO_GAS_PRICE, + ]; + const instance = await hre.deployments.deploy("Arbitrum_CustomGasToken_Adapter", { + from: deployer, + log: true, + skipIfAlreadyDeployed: false, + args, + }); + await hre.run("verify:verify", { address: instance.address, constructorArguments: args }); +}; + +module.exports = func; +func.tags = ["ArbitrumCustomGasTokenAdapter", "mainnet"]; diff --git a/deploy/consts.ts b/deploy/consts.ts index 1a720913..b05c5b2a 100644 --- a/deploy/consts.ts +++ b/deploy/consts.ts @@ -5,9 +5,12 @@ import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "../utils"; export const USDC = TOKEN_SYMBOLS_MAP.USDC.addresses; export const WETH = TOKEN_SYMBOLS_MAP.WETH.addresses; export const WMATIC = TOKEN_SYMBOLS_MAP.WMATIC.addresses; +export const AZERO = TOKEN_SYMBOLS_MAP.AZERO; export const QUOTE_TIME_BUFFER = 3600; export const FILL_DEADLINE_BUFFER = 6 * 3600; +export const ARBITRUM_MAX_SUBMISSION_COST = "10000000000000000"; +export const AZERO_GAS_PRICE = "240000000000"; export const L1_ADDRESS_MAP: { [key: number]: { [contractName: string]: string } } = { [CHAIN_IDs.MAINNET]: { @@ -48,6 +51,9 @@ export const L1_ADDRESS_MAP: { [key: number]: { [contractName: string]: string } zoraStandardBridge: "0x3e2Ea9B92B7E48A52296fD261dc26fd995284631", worldChainCrossDomainMessenger: "0xf931a81D18B1766d15695ffc7c1920a62b7e710a", worldChainStandardBridge: "0x470458C91978D2d929704489Ad730DC3E3001113", + l1AlephZeroInbox: "0x56D8EC76a421063e1907503aDd3794c395256AEb", + l1AlephZeroERC20GatewayRouter: "0xeBb17f398ed30d02F2e8733e7c1e5cf566e17812", + donationBox: "0x90285a96F5955A7279EF0C1e89A1B4f66d8E4dA7", }, [CHAIN_IDs.SEPOLIA]: { optimismCrossDomainMessenger: "0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef", diff --git a/package.json b/package.json index 50b8552c..ee3a8bc6 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "prepublish": "yarn build && hardhat export --export-all ./cache/massExport.json && ts-node ./scripts/processHardhatExport.ts && prettier --write ./deployments/deployments.json && yarn generate-contract-types" }, "dependencies": { - "@across-protocol/constants": "^3.1.16", + "@across-protocol/constants": "^3.1.17", "@coral-xyz/anchor": "^0.30.1", "@defi-wonderland/smock": "^2.3.4", "@eth-optimism/contracts": "^0.5.40", diff --git a/yarn.lock b/yarn.lock index 652119ac..7bb251a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@across-protocol/constants@^3.1.16": - version "3.1.16" - resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.16.tgz#c126085d29d4d051fd02a04c833d804d37c3c219" - integrity sha512-+U+AecGWnfY4b4sSfKBvsDj/+yXKEqpTXcZgI8GVVmUTkUhs1efA0kN4q3q10yy5TXI5TtagaG7R9yZg1zgKKg== +"@across-protocol/constants@^3.1.17": + version "3.1.17" + resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.17.tgz#1e43c87fbab06df3a1aab8993d7c5f746838e25d" + integrity sha512-mW++45vP04ahogsHFM5nE7ZKV8vmdxSO8gbBeP24VFxijrIYWqhISG67EU9pnAbgAIB58pT+ZmqdXI25iDmctA== "@across-protocol/contracts@^0.1.4": version "0.1.4"