From 22caf255589cb7c573fb13f3842e9cdab517be90 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 11 Feb 2025 13:18:05 -0500 Subject: [PATCH 1/6] WIP: Berachain --- README.md | 18 +++--- api_secrets.json.template | 4 ++ chain_config.json | 26 ++++++++ script/SafeConfig.sol | 2 + src/chains/Berachain/Common.sol | 61 +++++++++++++++++++ src/chains/Berachain/Intent.sol | 80 +++++++++++++++++++++++++ src/chains/Berachain/MetaTxn.sol | 48 +++++++++++++++ src/chains/Berachain/TakerSubmitted.sol | 51 ++++++++++++++++ 8 files changed, 282 insertions(+), 8 deletions(-) create mode 100644 src/chains/Berachain/Common.sol create mode 100644 src/chains/Berachain/Intent.sol create mode 100644 src/chains/Berachain/MetaTxn.sol create mode 100644 src/chains/Berachain/TakerSubmitted.sol diff --git a/README.md b/README.md index 2ce7f0cb..ac1002e1 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ your integration. * `0x0000000000001fF3684f28c67538d4D072C22734` on chains supporting the Cancun hardfork (Ethereum Mainnet, Ethereum Sepolia, Polygon, Base, Optimism, Arbitrum, Blast, Bnb, Mode, World Chain, Gnosis, Fantom Sonic, Ink, Monad - testnet, Avalanche) + testnet, Avalanche, Unichain, Berachain) * `0x0000000000005E88410CcDFaDe4a5EfaE4b49562` on chains supporting the Shanghai hardfork (Scroll, Mantle, Taiko) * `0x000000000000175a8b9bC6d539B3708EEd92EA6c` on chains supporting the London @@ -1331,7 +1331,7 @@ Second, test for common opcode support: ```bash export FOUNDRY_EVM_VERSION=london declare -r deployer_eoa='YOUR EOA ADDRESS HERE' -declare -r rpc_url='YOUR RPC URL HERE' # http://localhost:1248 if using frame.sh +declare -r rpc_url='YOUR RPC URL HERE' # http://127.0.0.1:1248 if using frame.sh declare -r -i chainid='CHAIN ID TO TEST HERE' forge clean forge build src/ChainCompatibility.sol @@ -1369,12 +1369,14 @@ of its receipt. -Third, create a new `src/chains/.sol` file. A good way to -start is by copying [`src/chains/Sepolia.sol`](src/chains/Sepolia.sol). You'll -need to change the names of all the contracts, remove references to missing -liquidity sources (presently MaverickV2), replace the `block.chainid` check in -the constructor, and replace the UniswapV3 forks. When adding new UniswapV3 -forks, be sure that the `factory` address is the address of the contract that +Third, create a new set of +`src/chains//{Common,TakerSubmitted,MetaTxn,Intent}.sol` +files. A good way to start is by copying +[`src/chains/Sepolia/*.sol`](src/chains/Sepolia/). You'll need to change the +names of all the contracts, remove references to missing liquidity sources +(presently MaverickV2 and UniswapV4), replace the `block.chainid` check in the +constructor, and replace the UniswapV3 forks. When adding new UniswapV3 forks, +be sure that the `factory` address is the address of the contract that `CREATE2`'s the pool. Triple check that the deployed pools aren't upgradeable proxies and that the `data` argument is passed through the callback unmodified. _**This is critical for security.**_ Some chains have a form of diff --git a/api_secrets.json.template b/api_secrets.json.template index 46bcaa33..077db629 100644 --- a/api_secrets.json.template +++ b/api_secrets.json.template @@ -75,5 +75,9 @@ "unichain": { "etherscanKey": "", "rpcUrl": "" + }, + "berachain": { + "etherscanKey": "", + "rpcUrl": "" } } diff --git a/chain_config.json b/chain_config.json index 4dcc0693..4ed5b6f8 100644 --- a/chain_config.json +++ b/chain_config.json @@ -517,5 +517,31 @@ "deployer": "0x00000000000004533Fe15556B1E086BB1A72cEae" }, "etherscanApi": "https://api.uniscan.xyz/api" + }, + "berachain": { + "chainId": 80094, + "displayName": "Berachain", + "isShanghai": true, + "isCancun": true, + "extraFlags": "--legacy", + "gasMultiplierPercent": 200, + "minGasPriceGwei": 1, + "safe": { + "singleton": null, + "factory": null, + "fallback": null, + "multiCall": null, + "apiUrl": "NOT SUPPORTED" + }, + "governance": { + "upgradeSafe": null, + "deploymentSafe": null, + "pause": "0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30" + }, + "deployment": { + "allowanceHolder": "0x0000000000001fF3684f28c67538d4D072C22734", + "deployer": "0x00000000000004533Fe15556B1E086BB1A72cEae" + }, + "etherscanApi": "https://api.berascan.com/api" } } diff --git a/script/SafeConfig.sol b/script/SafeConfig.sol index e28bb9ac..a48ed2c0 100644 --- a/script/SafeConfig.sol +++ b/script/SafeConfig.sol @@ -26,6 +26,7 @@ library SafeConfig { || block.chainid == 43114 // avalanche || block.chainid == 57073 // ink || block.chainid == 59144 // linea + || block.chainid == 80094 // berachain || block.chainid == 81457 // blast || block.chainid == 167000 // taiko || block.chainid == 534352 // scroll @@ -54,6 +55,7 @@ library SafeConfig { || block.chainid == 43114 // avalanche || block.chainid == 57073 // ink || block.chainid == 59144 // linea + || block.chainid == 80094 // berachain || block.chainid == 81457 // blast || block.chainid == 167000 // taiko || block.chainid == 534352 // scroll diff --git a/src/chains/Berachain/Common.sol b/src/chains/Berachain/Common.sol new file mode 100644 index 00000000..04a3b36d --- /dev/null +++ b/src/chains/Berachain/Common.sol @@ -0,0 +1,61 @@ +// 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 {UnknownForkId} from "../../core/SettlerErrors.sol"; + +/* +import { + uniswapV3BerachainFactory, + uniswapV3InitHash, + uniswapV3ForkId, + IUniswapV3Callback +} from "../../core/univ3forks/UniswapV3.sol"; +*/ + +// Solidity inheritance is stupid +import {SettlerAbstract} from "../../SettlerAbstract.sol"; + +abstract contract BerachainMixin is FreeMemory, SettlerBase { + constructor() { + assert(block.chainid == 80094 || block.chainid == 31337); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + virtual + override(/*SettlerAbstract, */SettlerBase) + DANGEROUS_freeMemory + returns (bool) + { + if (super._dispatch(i, action, data)) { + return true; + } else { + return false; + } + return true; + } + + function _uniV3ForkInfo(uint8 forkId) + internal + pure + override + returns (address factory, bytes32 initHash, uint32 callbackSelector) + { + /* + if (forkId == uniswapV3ForkId) { + factory = uniswapV3BerachainFactory; + initHash = uniswapV3InitHash; + callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); + } else { + */ + revert UnknownForkId(forkId); + //} + } +} diff --git a/src/chains/Berachain/Intent.sol b/src/chains/Berachain/Intent.sol new file mode 100644 index 00000000..6494c637 --- /dev/null +++ b/src/chains/Berachain/Intent.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.25; + +import {BerachainSettlerMetaTxn} 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} from "../../Context.sol"; +import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; +import {Permit2PaymentMetaTxn} from "../../core/Permit2Payment.sol"; + +/// @custom:security-contact security@0x.org +contract BerachainSettlerIntent is SettlerIntent, BerachainSettlerMetaTxn { + constructor(bytes20 gitCommit) BerachainSettlerMetaTxn(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(BerachainSettlerMetaTxn, SettlerBase, SettlerAbstract) + returns (bool) + { + return super._dispatch(i, action, data); + } + + function _msgSender() internal view override(SettlerIntent, BerachainSettlerMetaTxn) 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(BerachainSettlerMetaTxn, SettlerMetaTxn) + returns (bool) + { + return super._dispatchVIP(action, data, sig); + } + + function _permitToSellAmount(ISignatureTransfer.PermitTransferFrom memory permit) + internal + pure + override(SettlerIntent, Permit2PaymentAbstract, Permit2PaymentMetaTxn) + returns (uint256) + { + return super._permitToSellAmount(permit); + } +} diff --git a/src/chains/Berachain/MetaTxn.sol b/src/chains/Berachain/MetaTxn.sol new file mode 100644 index 00000000..71c8f833 --- /dev/null +++ b/src/chains/Berachain/MetaTxn.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.25; + +import {BerachainMixin} from "./Common.sol"; +import {SettlerMetaTxn} from "../../SettlerMetaTxn.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 {AbstractContext} from "../../Context.sol"; + +/// @custom:security-contact security@0x.org +contract BerachainSettlerMetaTxn is SettlerMetaTxn, BerachainMixin { + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} + + function _dispatchVIP(uint256 action, bytes calldata data, bytes calldata sig) + internal + virtual + override + DANGEROUS_freeMemory + returns (bool) + { + if (super._dispatchVIP(action, data, sig)) { + return true; + } else { + return false; + } + return true; + } + + // Solidity inheritance is stupid + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + virtual + override(SettlerAbstract, SettlerBase, BerachainMixin) + returns (bool) + { + return super._dispatch(i, action, data); + } + + function _msgSender() internal view virtual override(SettlerMetaTxn, AbstractContext) returns (address) { + return super._msgSender(); + } +} diff --git a/src/chains/Berachain/TakerSubmitted.sol b/src/chains/Berachain/TakerSubmitted.sol new file mode 100644 index 00000000..8e2f3f09 --- /dev/null +++ b/src/chains/Berachain/TakerSubmitted.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.25; + +import {BerachainMixin} from "./Common.sol"; +import {Settler} from "../../Settler.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 {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; +import {AbstractContext} from "../../Context.sol"; + +/// @custom:security-contact security@0x.org +contract BerachainSettler is Settler, BerachainMixin { + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} + + function _dispatchVIP(uint256 action, bytes calldata data) internal override DANGEROUS_freeMemory returns (bool) { + if (super._dispatchVIP(action, data)) { + return true; + } else { + return false; + } + return true; + } + + // Solidity inheritance is stupid + function _isRestrictedTarget(address target) + internal + pure + override(Settler, Permit2PaymentAbstract) + returns (bool) + { + return super._isRestrictedTarget(target); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + override(SettlerAbstract, SettlerBase, BerachainMixin) + returns (bool) + { + return super._dispatch(i, action, data); + } + + function _msgSender() internal view override(Settler, AbstractContext) returns (address) { + return super._msgSender(); + } +} From abb82fb6c343587606bb7c24bf54b00456dcf79f Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 11 Feb 2025 13:26:37 -0500 Subject: [PATCH 2/6] Configure Safe{Wallet} contracts for Berachain --- chain_config.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chain_config.json b/chain_config.json index 4ed5b6f8..4b7e1b1b 100644 --- a/chain_config.json +++ b/chain_config.json @@ -527,10 +527,10 @@ "gasMultiplierPercent": 200, "minGasPriceGwei": 1, "safe": { - "singleton": null, - "factory": null, - "fallback": null, - "multiCall": null, + "singleton": "0xfb1bffC9d739B8D520DaF37dF666da4C687191EA", + "factory": "0xC22834581EbC8527d974F8a1c97E1bEA4EF910BC", + "fallback": "0x017062a1dE2FE6b99BE3d9d37841FeD19F573804", + "multiCall": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", "apiUrl": "NOT SUPPORTED" }, "governance": { From 7cace3b5824189b89fa35cd62a2361973a950335 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 11 Feb 2025 13:27:03 -0500 Subject: [PATCH 3/6] `CHANGELOG.md` --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aeef29ac..a91f45a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Master list of UniV3 forks: * Deploy Settler to Unichain network * Add UniswapV3 UniV3 fork to Unichain * Add UniswapV4 actions to Unichain +* Deploy Settler to Berachain network ## 2025-01-23 From a0efea2346aefec11236d6b31e88f0f0ed9f1ab2 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 11 Feb 2025 15:43:09 -0500 Subject: [PATCH 4/6] Sourcify does not support Berachain --- sh/common.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sh/common.sh b/sh/common.sh index 0fefe24b..f8c8dc52 100644 --- a/sh/common.sh +++ b/sh/common.sh @@ -113,7 +113,9 @@ function verify_contract { else forge verify-contract --watch --verifier custom --verifier-api-key "$(get_api_secret etherscanKey)" --verifier-url "$(get_config etherscanApi)" --constructor-args "$_verify_constructor_args" "$_verify_deployed_address" "$_verify_source_path" fi - if (( chainid != 146 )) && (( chainid != 480 )) && (( chainid != 10143 )) && (( chainid != 57073 )) && (( chainid != 81457 )) && (( chainid != 167000 )); then # Sourcify doesn't support Sonic, World Chain, MonadTestnet, Ink, Blast, or Taiko + + # Sourcify doesn't support Sonic, World Chain, MonadTestnet, Ink, Berachain, Blast, or Taiko + if (( chainid != 146 )) && (( chainid != 480 )) && (( chainid != 10143 )) && (( chainid != 57073 )) && (( chainid != 80094 )) && (( chainid != 81457 )) && (( chainid != 167000 )); then forge verify-contract --watch --chain $chainid --verifier sourcify --constructor-args "$_verify_constructor_args" "$_verify_deployed_address" "$_verify_source_path" fi } From bff8294a54d19f44284e002777b853b2cb32942d Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 11 Feb 2025 15:47:16 -0500 Subject: [PATCH 5/6] Add Safe{Wallet} addresses for Berachain --- chain_config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain_config.json b/chain_config.json index 4b7e1b1b..2faf8e85 100644 --- a/chain_config.json +++ b/chain_config.json @@ -534,8 +534,8 @@ "apiUrl": "NOT SUPPORTED" }, "governance": { - "upgradeSafe": null, - "deploymentSafe": null, + "upgradeSafe": "0xf36b9f50E59870A24F42F9Ba43b2aD0A4b8f2F51", + "deploymentSafe": "0x8E5DE7118a596E99B0563D3022039c11927f4827", "pause": "0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30" }, "deployment": { From 319d1afa6fb8a5934727367733d4d0ccfef2e0b4 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 12 Feb 2025 07:29:26 -0500 Subject: [PATCH 6/6] Add Bulla Exchange and KodiakV3 UniV3 forks on Berachain --- CHANGELOG.md | 4 ++++ src/chains/Berachain/Common.sol | 26 ++++++++++++-------------- src/core/univ3forks/Bulla.sol | 5 +++++ src/core/univ3forks/KodiakV3.sol | 6 ++++++ 4 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 src/core/univ3forks/Bulla.sol create mode 100644 src/core/univ3forks/KodiakV3.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index a91f45a2..9ee74257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ Master list of UniV3 forks: 27. SpookySwap 28. Wagmi 29. SwapX (Algebra-like) + 30. KodiakV3 + 31. Bulla Exchange (Algebra-like) --- @@ -49,6 +51,8 @@ Master list of UniV3 forks: * Add UniswapV3 UniV3 fork to Unichain * Add UniswapV4 actions to Unichain * Deploy Settler to Berachain network + * Add KodiakV3 UniV3 fork to Berachain + * Add Bulla Exchange UniV3 (Algebra style) fork to Berachain ## 2025-01-23 diff --git a/src/chains/Berachain/Common.sol b/src/chains/Berachain/Common.sol index 04a3b36d..9e744543 100644 --- a/src/chains/Berachain/Common.sol +++ b/src/chains/Berachain/Common.sol @@ -10,14 +10,10 @@ import {ISettlerActions} from "../../ISettlerActions.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; import {UnknownForkId} from "../../core/SettlerErrors.sol"; -/* -import { - uniswapV3BerachainFactory, - uniswapV3InitHash, - uniswapV3ForkId, - IUniswapV3Callback -} from "../../core/univ3forks/UniswapV3.sol"; -*/ +import {kodiakV3Factory, kodiakV3InitHash, kodiakV3ForkId} from "../../core/univ3forks/KodiakV3.sol"; +import {IUniswapV3Callback} from "../../core/univ3forks/UniswapV3.sol"; +import {bullaFactory, bullaForkId} from "../../core/univ3forks/Bulla.sol"; +import {algebraV4InitHash, IAlgebraCallback} from "../../core/univ3forks/Algebra.sol"; // Solidity inheritance is stupid import {SettlerAbstract} from "../../SettlerAbstract.sol"; @@ -48,14 +44,16 @@ abstract contract BerachainMixin is FreeMemory, SettlerBase { override returns (address factory, bytes32 initHash, uint32 callbackSelector) { - /* - if (forkId == uniswapV3ForkId) { - factory = uniswapV3BerachainFactory; - initHash = uniswapV3InitHash; + if (forkId == kodiakV3ForkId) { + factory = kodiakV3Factory; + initHash = kodiakV3InitHash; callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); + } else if (forkId == bullaForkId) { + factory = bullaFactory; + initHash = algebraV4InitHash; + callbackSelector = uint32(IAlgebraCallback.algebraSwapCallback.selector); } else { - */ revert UnknownForkId(forkId); - //} + } } } diff --git a/src/core/univ3forks/Bulla.sol b/src/core/univ3forks/Bulla.sol new file mode 100644 index 00000000..e4df6130 --- /dev/null +++ b/src/core/univ3forks/Bulla.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +address constant bullaFactory = 0x425EC3de5FEB62897dbe239Aa218B2DC035DCDF1; +uint8 constant bullaForkId = 31; diff --git a/src/core/univ3forks/KodiakV3.sol b/src/core/univ3forks/KodiakV3.sol new file mode 100644 index 00000000..884d58f5 --- /dev/null +++ b/src/core/univ3forks/KodiakV3.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +address constant kodiakV3Factory = 0xD84CBf0B02636E7f53dB9E5e45A616E05d710990; +bytes32 constant kodiakV3InitHash = 0xd8e2091bc519b509176fc39aeb148cc8444418d3ce260820edc44e806c2c2339; +uint8 constant kodiakV3ForkId = 30;