Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ your integration.
hardfork (Ethereum mainnet, Ethereum Sepolia testnet, Polygon, Base, Optimism,
Arbitrum, Blast, Bnb, Mode, World Chain, Gnosis, Fantom Sonic, Ink, Monad
testnet, Avalanche, Unichain, Berachain, Scroll, HyperEvm, Katana, Plasma,
Monad mainnet, Abstract, Linea)
Monad mainnet, Abstract, Linea, MegaEth)
* `0x0000000000005E88410CcDFaDe4a5EfaE4b49562` on chains supporting the Shanghai
hardfork (Mantle, Taiko)

Expand Down Expand Up @@ -1408,7 +1408,12 @@ Zeroth, verify the configuration for your chain in
[`chain_config.json`](chain_config.json),
[`api_secrets.json.template`](api_secrets.json.template), and
[`script/SafeConfig.sol`](script/SafeConfig.sol). Add the new chain to the list
of `AllowanceHolder` addresses at the top of this file.
of `AllowanceHolder` addresses at the top of this file. Pay attention to the
`extraFlags` and `extraScriptFlags` fields. `extraFlags` should be `--legacy` on
L2s that bill the DA fee directly in the native asset (e.g. OP stack
rollups). `extraScriptFlags` should have `--isolate` on chains that aren't
EraVM. `extraScriptFlags` should have `--skip-simulation` on chains with weird
gas rules (i.e. Arbitrum, Mantle, Monad, MegaEth).

First, you need somebody to give you a copy of `secrets.json`. If you don't have
this, give up. Install [`scrypt`](https://github.com/Tarsnap/scrypt) and use it
Expand Down
4 changes: 4 additions & 0 deletions api_secrets.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,9 @@
"abstract": {
"etherscanKey": "",
"rpcUrl": ""
},
"megaeth": {
"rpcUrl": "",
"blockscoutApi": ""
}
}
29 changes: 25 additions & 4 deletions chain_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
"isCancun": true,
"isEraVm": false,
"extraFlags": "--legacy",
"extraScriptFlags": "--isolate",
"extraScriptFlags": "--isolate --skip-simulation",
"gasMultiplierPercent": 300,
"minGasPriceGwei": 1,
"wnative": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
Expand Down Expand Up @@ -379,7 +379,7 @@
"isCancun": false,
"isEraVm": false,
"extraFlags": "--legacy",
"extraScriptFlags": "--isolate",
"extraScriptFlags": "--isolate --skip-simulation",
"gasMultiplierPercent": 200,
"minGasPriceGwei": 1,
"wnative": "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8",
Expand Down Expand Up @@ -572,7 +572,8 @@
"forwardingMultiCall": "0x00000000000000CF9E3c5A26621af382fA17f24f",
"crossChainFactory": "0x00000000000000304861c3aDfb80dd5ebeC96325"
},
"etherscanApi": "https://api.etherscan.io/v2/api?chainid=146"
"etherscanApi": "https://api.etherscan.io/v2/api?chainid=146",
"sourcifyApi": "https://sourcify.dev/server/"
},
"ink": {
"chainId": 57073,
Expand Down Expand Up @@ -816,7 +817,7 @@
"isCancun": true,
"isEraVm": false,
"extraFlags": "",
"extraScriptFlags": "--isolate",
"extraScriptFlags": "--isolate --skip-simulation",
"gasMultiplierPercent": 110,
"minGasPriceGwei": 52,
"safe": {
Expand Down Expand Up @@ -906,5 +907,25 @@
"pause": "0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30"
},
"etherscanApi": "https://api.etherscan.io/v2/api?chainid=2741"
},
"megaeth": {
"chainId": 4326,
"displayName": "MegaEth",
"wnative": "0x4200000000000000000000000000000000000006",
"isShanghai": true,
"isCancun": true,
"isEraVm": false,
"extraFlags": "",
"extraScriptFlags": "--isolate --skip-simulation",
"gasMultiplierPercent": 200,
"minGasPriceGwei": 1,
"safe": {
"toehold": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",
"singleton": "0xfb1bffC9d739B8D520DaF37dF666da4C687191EA",
"factory": "0xC22834581EbC8527d974F8a1c97E1bEA4EF910BC",
"fallback": "0x017062a1dE2FE6b99BE3d9d37841FeD19F573804",
"multiCall": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B",
"apiUrl": "NOT SUPPORTED"
}
}
}
3 changes: 3 additions & 0 deletions script/SafeConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ library SafeConfig {
|| block.chainid == 480 // worldchain
|| block.chainid == 999 // hyperevm
|| block.chainid == 2741 // abstract
|| block.chainid == 4326 // megaeth
|| block.chainid == 5000 // mantle
|| block.chainid == 8453 // base
|| block.chainid == 9745 // plasma
Expand Down Expand Up @@ -58,6 +59,7 @@ library SafeConfig {
|| block.chainid == 480 // worldchain
|| block.chainid == 999 // hyperevm
|| block.chainid == 2741 // abstract
|| block.chainid == 4326 // megaeth
|| block.chainid == 5000 // mantle
|| block.chainid == 8453 // base
|| block.chainid == 9745 // plasma
Expand Down Expand Up @@ -97,6 +99,7 @@ library SafeConfig {
|| block.chainid == 146 // sonic
|| block.chainid == 480 // worldchain
|| block.chainid == 999 // hyperevm
|| block.chainid == 4326 // megaeth
|| block.chainid == 5000 // mantle
|| block.chainid == 8453 // base
|| block.chainid == 9745 // plasma
Expand Down
15 changes: 12 additions & 3 deletions sh/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,24 @@ function verify_contract {
shift

declare _verify_etherscanApi
_verify_etherscanApi="$(get_config etherscanApi)"
_verify_etherscanApi="$(get_api_secret etherscanApi)"
if [[ ${_verify_etherscanApi:-null} == [nN][uU][lL][lL] ]] ; then
_verify_etherscanApi="$(get_config etherscanApi)"
fi
declare -r _verify_etherscanApi

declare _verify_blockscoutApi
_verify_blockscoutApi="$(get_config blockscoutApi)"
_verify_blockscoutApi="$(get_api_secret blockscoutApi)"
if [[ ${_verify_blockscoutApi:-null} == [nN][uU][lL][lL] ]] ; then
_verify_blockscoutApi="$(get_config blockscoutApi)"
fi
declare -r _verify_blockscoutApi

declare _verify_sourcifyApi
_verify_sourcifyApi="$(get_config sourcifyApi)"
_verify_sourcifyApi="$(get_api_secret sourcifyApi)"
if [[ ${_verify_sourcifyApi:-null} == [nN][uU][lL][lL] ]] ; then
_verify_sourcifyApi="$(get_config sourcifyApi)"
fi
declare -r _verify_sourcifyApi

if [[ ${_verify_etherscanApi:-null} != [nN][uU][lL][lL] ]] ; then
Expand Down
6 changes: 3 additions & 3 deletions sh/common_gas.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ function apply_gas_multiplier {
declare -i _gas_estimate="$1"
shift

# Mantle has funky gas rules, exclude it from this logic
if (( chainid != 5000 )) && (( _gas_estimate > eip7825_gas_limit )) ; then
# Mantle and MegaEth have funky gas rules, exclude them from this logic
if (( chainid != 4326 )) && (( chainid != 5000 )) && (( _gas_estimate > eip7825_gas_limit )) ; then
echo 'Gas estimate without buffer /already/ exceeds the EIP-7825 limit' >&2
exit 1
fi

declare -i _gas_limit=$((_gas_estimate * gas_estimate_multiplier / 100))

if (( chainid != 5000 )) && (( _gas_limit > eip7825_gas_limit )) ; then
if (( chainid != 4326 )) && (( chainid != 5000 )) && (( _gas_limit > eip7825_gas_limit )) ; then
declare _gas_limit_keep_going
IFS='' read -p 'Gas limit with multiplier exceeds EIP-7825 limit. Cap gas limit and keep going? [y/N]: ' -e -r -i n _gas_limit_keep_going
declare -r _gas_limit_keep_going
Expand Down
4 changes: 2 additions & 2 deletions sh/deploy_new_bridge_settler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ while (( ${#deploy_calldatas[@]} >= 3 )) ; do

declare packed_signatures
packed_signatures="$(retrieve_signatures bridge_settler_confirmation "$deploy_calldata" $operation "$target")"

declare -a args=(
"$safe_address" "$execTransaction_sig"
# to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, signatures
Expand All @@ -157,7 +157,7 @@ while (( ${#deploy_calldatas[@]} >= 3 )) ; do
declare -i gas_limit
gas_limit="$(apply_gas_multiplier $gas_estimate)"
declare -r -i gas_limit

if [[ $wallet_type = 'frame' ]] ; then
cast send --confirmations 10 --from "$signer" --rpc-url 'http://127.0.0.1:1248/' --chain $chainid --gas-price $gas_price --gas-limit $gas_limit "${wallet_args[@]}" $(get_config extraFlags) "${args[@]}"
else
Expand Down
25 changes: 25 additions & 0 deletions src/chains/MegaEth/BridgeSettler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.25;

import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {SettlerAbstract} from "../../SettlerAbstract.sol";
import {IBridgeSettlerActions} from "../../bridge/IBridgeSettlerActions.sol";
import {BridgeSettler, BridgeSettlerBase} from "../../bridge/BridgeSettler.sol";

contract MegaEthBridgeSettler is BridgeSettler {
constructor(bytes20 gitCommit) BridgeSettlerBase(gitCommit) {
assert(block.chainid == 4326 || block.chainid == 31337);
}

function _dispatch(uint256 i, uint256 action, bytes calldata data)
internal
override(BridgeSettlerBase, SettlerAbstract)
returns (bool)
{
if (super._dispatch(i, action, data)) {
return true;
} else {
return false;
}
}
}
49 changes: 49 additions & 0 deletions src/chains/MegaEth/Common.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.25;

import {SettlerBase} from "../../SettlerBase.sol";

import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {FreeMemory} from "../../utils/FreeMemory.sol";

import {ISettlerActions} from "../../ISettlerActions.sol";
import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol";
import {revertUnknownForkId} from "../../core/SettlerErrors.sol";

// Solidity inheritance is stupid
import {SettlerAbstract} from "../../SettlerAbstract.sol";

abstract contract MegaEthMixin is FreeMemory, SettlerBase {
constructor() {
assert(block.chainid == 4326 || block.chainid == 31337);
}

function _dispatch(uint256 i, uint256 action, bytes calldata data)
internal
virtual
override(/* SettlerAbstract, */ SettlerBase)
DANGEROUS_freeMemory
returns (bool)
{
// This does not make use of `super._dispatch`. This chain's Settler is extremely
// stripped-down and has almost no capabilities
if (action == uint32(ISettlerActions.BASIC.selector)) {
(IERC20 sellToken, uint256 bps, address pool, uint256 offset, bytes memory _data) =
abi.decode(data, (IERC20, uint256, address, uint256, bytes));

basicSellToPool(sellToken, bps, pool, offset, _data);
} else {
return false;
}
return true;
}

function _uniV3ForkInfo(uint8 forkId)
internal
pure
override
returns (address factory, bytes32 initHash, uint32 callbackSelector)
{
revertUnknownForkId(forkId);
}
}
97 changes: 97 additions & 0 deletions src/chains/MegaEth/Intent.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.25;

import {MegaEthSettlerMetaTxn} from "./MetaTxn.sol";
import {SettlerIntent} from "../../SettlerIntent.sol";

import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol";
import {ISettlerActions} from "../../ISettlerActions.sol";

// Solidity inheritance is stupid
import {SettlerAbstract} from "../../SettlerAbstract.sol";
import {SettlerBase} from "../../SettlerBase.sol";
import {SettlerMetaTxn} from "../../SettlerMetaTxn.sol";
import {SettlerIntent} from "../../SettlerIntent.sol";
import {AbstractContext, Context} from "../../Context.sol";
import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol";
import {Permit2PaymentMetaTxn} from "../../core/Permit2Payment.sol";

/// @custom:security-contact security@0x.org
contract MegaEthSettlerIntent is SettlerIntent, MegaEthSettlerMetaTxn {
constructor(bytes20 gitCommit) MegaEthSettlerMetaTxn(gitCommit) {}

// Solidity inheritance is stupid
function executeMetaTxn(
AllowedSlippage calldata slippage,
bytes[] calldata actions,
bytes32, /* zid & affiliate */
address msgSender,
bytes calldata sig
) public override(SettlerIntent, SettlerMetaTxn) returns (bool) {
return super.executeMetaTxn(slippage, actions, bytes32(0), msgSender, sig);
}

function _dispatch(uint256 i, uint256 action, bytes calldata data)
internal
override(MegaEthSettlerMetaTxn, SettlerBase, SettlerAbstract)
returns (bool)
{
return super._dispatch(i, action, data);
}

function _isForwarded() internal view override(AbstractContext, Context, SettlerIntent) returns (bool) {
return super._isForwarded();
}

function _msgData() internal view override(AbstractContext, Context, SettlerIntent) returns (bytes calldata) {
return super._msgData();
}

function _msgSender() internal view override(SettlerIntent, MegaEthSettlerMetaTxn) returns (address) {
return super._msgSender();
}

function _witnessTypeSuffix()
internal
pure
override(SettlerIntent, Permit2PaymentMetaTxn)
returns (string memory)
{
return super._witnessTypeSuffix();
}

function _mandatorySlippageCheck() internal pure override(SettlerBase, SettlerIntent) returns (bool) {
return super._mandatorySlippageCheck();
}

function _tokenId() internal pure override(SettlerIntent, SettlerMetaTxn, SettlerAbstract) returns (uint256) {
return super._tokenId();
}

function _dispatchVIP(uint256 action, bytes calldata data, bytes calldata sig)
internal
override(MegaEthSettlerMetaTxn, SettlerMetaTxn)
returns (bool)
{
return super._dispatchVIP(action, data, sig);
}

function _permitToSellAmountCalldata(ISignatureTransfer.PermitTransferFrom calldata permit)
internal
view
override(SettlerIntent, Permit2PaymentAbstract, Permit2PaymentMetaTxn)
returns (uint256)
{
return super._permitToSellAmountCalldata(permit);
}

function _permitToSellAmount(ISignatureTransfer.PermitTransferFrom memory permit)
internal
view
override(SettlerIntent, Permit2PaymentAbstract, Permit2PaymentMetaTxn)
returns (uint256)
{
return super._permitToSellAmount(permit);
}
}
Loading