Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Berachain #303

Merged
merged 8 commits into from
Feb 12, 2025
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Master list of UniV3 forks:
27. SpookySwap
28. Wagmi
29. SwapX (Algebra-like)
30. KodiakV3
31. Bulla Exchange (Algebra-like)

---

Expand All @@ -48,6 +50,9 @@ 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
* Add KodiakV3 UniV3 fork to Berachain
* Add Bulla Exchange UniV3 (Algebra style) fork to Berachain

## 2025-01-23

Expand Down
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1369,12 +1369,14 @@ of its receipt.

</details>

Third, create a new `src/chains/<CHAIN_DISPLAY_NAME>.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/<CHAIN_DISPLAY_NAME>/{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
Expand Down
4 changes: 4 additions & 0 deletions api_secrets.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,9 @@
"unichain": {
"etherscanKey": "",
"rpcUrl": ""
},
"berachain": {
"etherscanKey": "",
"rpcUrl": ""
}
}
26 changes: 26 additions & 0 deletions chain_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -519,5 +519,31 @@
},
"etherscanApi": "https://api.uniscan.xyz/api",
"blockscoutApi": "https://unichain.blockscout.com/api"
},
"berachain": {
"chainId": 80094,
"displayName": "Berachain",
"isShanghai": true,
"isCancun": true,
"extraFlags": "--legacy",
"gasMultiplierPercent": 200,
"minGasPriceGwei": 1,
"safe": {
"singleton": "0xfb1bffC9d739B8D520DaF37dF666da4C687191EA",
"factory": "0xC22834581EbC8527d974F8a1c97E1bEA4EF910BC",
"fallback": "0x017062a1dE2FE6b99BE3d9d37841FeD19F573804",
"multiCall": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B",
"apiUrl": "NOT SUPPORTED"
},
"governance": {
"upgradeSafe": "0xf36b9f50E59870A24F42F9Ba43b2aD0A4b8f2F51",
"deploymentSafe": "0x8E5DE7118a596E99B0563D3022039c11927f4827",
"pause": "0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30"
},
"deployment": {
"allowanceHolder": "0x0000000000001fF3684f28c67538d4D072C22734",
"deployer": "0x00000000000004533Fe15556B1E086BB1A72cEae"
},
"etherscanApi": "https://api.berascan.com/api"
}
}
2 changes: 2 additions & 0 deletions script/SafeConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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
Expand Down Expand Up @@ -56,6 +57,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
Expand Down
4 changes: 2 additions & 2 deletions sh/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ function verify_contract {
declare -r -i _verify_source_blockscout=$((chainid == 130 || chainid == 480 || chainid == 10143 || chainid == 34443 || chainid == 57073))
# all other chains use Etherscan; Unichain and WorldChain use both
declare -r -i _verify_source_etherscan=$((chainid == 130 || chainid == 480 || ! _verify_source_blockscout))
# Sourcify doesn't support Unichain, Sonic, WorldChain, MonadTestnet, Ink, Blast, or Taiko
declare -r -i _verify_source_sourcify=$(( chainid != 130 && chainid != 146 && chainid != 480 && chainid != 10143 && chainid != 57073 && chainid != 81457 && chainid != 167000 ))
# Sourcify doesn't support Unichain, Sonic, WorldChain, MonadTestnet, Ink, Berachain, Blast, or Taiko
declare -r -i _verify_source_sourcify=$(( chainid != 130 && chainid != 146 && chainid != 480 && chainid != 10143 && chainid != 57073 && chainid != 80094 && chainid != 81457 && chainid != 167000 ))

if (( _verify_source_blockscout )) ; then
declare _verify_blockscoutApi
Expand Down
59 changes: 59 additions & 0 deletions src/chains/Berachain/Common.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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 {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";

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 == 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);
}
}
}
80 changes: 80 additions & 0 deletions src/chains/Berachain/Intent.sol
Original file line number Diff line number Diff line change
@@ -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 [email protected]
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);
}
}
48 changes: 48 additions & 0 deletions src/chains/Berachain/MetaTxn.sol
Original file line number Diff line number Diff line change
@@ -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 [email protected]
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();
}
}
51 changes: 51 additions & 0 deletions src/chains/Berachain/TakerSubmitted.sol
Original file line number Diff line number Diff line change
@@ -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 [email protected]
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();
}
}
5 changes: 5 additions & 0 deletions src/core/univ3forks/Bulla.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

address constant bullaFactory = 0x425EC3de5FEB62897dbe239Aa218B2DC035DCDF1;
uint8 constant bullaForkId = 31;
6 changes: 6 additions & 0 deletions src/core/univ3forks/KodiakV3.sol
Original file line number Diff line number Diff line change
@@ -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;
Loading