diff --git a/op-bindings/bindings/l1block.go b/op-bindings/bindings/l1block.go index 404db7b97a2c0..c0d9864252986 100644 --- a/op-bindings/bindings/l1block.go +++ b/op-bindings/bindings/l1block.go @@ -30,8 +30,8 @@ var ( // L1BlockMetaData contains all meta data concerning the L1Block contract. var L1BlockMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"_timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061025a806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806364ca23ef1161005b57806364ca23ef146100bc5780638381f58a146100fd578063b80777ea14610111578063e591b2821461013157600080fd5b8063042c2f571461008257806309bd5a60146100975780635cf24969146100b3575b600080fd5b6100956100903660046101f6565b610171565b005b6100a060025481565b6040519081526020015b60405180910390f35b6100a060015481565b6000546100e490700100000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100aa565b6000546100e49067ffffffffffffffff1681565b6000546100e49068010000000000000000900467ffffffffffffffff1681565b61014c73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100aa565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146101be576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60801b60409390931b90931791909117600055600155600255565b803567ffffffffffffffff811681146101f157600080fd5b919050565b600080600080600060a0868803121561020e57600080fd5b610217866101d9565b9450610225602087016101d9565b93506040860135925060608601359150610241608087016101d9565b9050929550929590935056fea164736f6c634300080a000a", + ABI: "[{\"inputs\":[],\"name\":\"OnlyDepositor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"averageBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"_timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50610433806100206000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806364ca23ef1161005b57806364ca23ef146100d05780638381f58a14610111578063b80777ea14610125578063e591b2821461014557600080fd5b8063042c2f571461008d57806309bd5a60146100a25780635cf24969146100be5780635f528dc3146100c7575b600080fd5b6100a061009b366004610365565b610185565b005b6100ab60035481565b6040519081526020015b60405180910390f35b6100ab60015481565b6100ab60025481565b6000546100f890700100000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100b5565b6000546100f89067ffffffffffffffff1681565b6000546100f89068010000000000000000900467ffffffffffffffff1681565b61016073deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146101d2576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608081901b604085901b8617176000819055600184905560038390556101f784610202565b600255505050505050565b600061021060025483610216565b92915050565b60008061023c84610237676124fee993bc0000678ac7230489e80000610286565b6102a2565b9050600061025e846102376729a2241af62c0000678ac7230489e80000610286565b9050670de0b6b3a764000061027383836102f3565b61027d91906103eb565b95945050505050565b600061029b83670de0b6b3a764000084610329565b9392505050565b6000826102b157506000610210565b828202828482816102c4576102c46103bc565b041461029b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915050610210565b60008282018381101561029b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915050610210565b82820281151584158583048514171661034157600080fd5b0492915050565b803567ffffffffffffffff8116811461036057600080fd5b919050565b600080600080600060a0868803121561037d57600080fd5b61038686610348565b945061039460208701610348565b935060408601359250606086013591506103b060808701610348565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610421577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c634300080a000a", } // L1BlockABI is the input ABI used to generate the binding from. @@ -232,6 +232,37 @@ func (_L1Block *L1BlockCallerSession) DEPOSITORACCOUNT() (common.Address, error) return _L1Block.Contract.DEPOSITORACCOUNT(&_L1Block.CallOpts) } +// AverageBasefee is a free data retrieval call binding the contract method 0x5f528dc3. +// +// Solidity: function averageBasefee() view returns(uint256) +func (_L1Block *L1BlockCaller) AverageBasefee(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _L1Block.contract.Call(opts, &out, "averageBasefee") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// AverageBasefee is a free data retrieval call binding the contract method 0x5f528dc3. +// +// Solidity: function averageBasefee() view returns(uint256) +func (_L1Block *L1BlockSession) AverageBasefee() (*big.Int, error) { + return _L1Block.Contract.AverageBasefee(&_L1Block.CallOpts) +} + +// AverageBasefee is a free data retrieval call binding the contract method 0x5f528dc3. +// +// Solidity: function averageBasefee() view returns(uint256) +func (_L1Block *L1BlockCallerSession) AverageBasefee() (*big.Int, error) { + return _L1Block.Contract.AverageBasefee(&_L1Block.CallOpts) +} + // Basefee is a free data retrieval call binding the contract method 0x5cf24969. // // Solidity: function basefee() view returns(uint256) diff --git a/op-bindings/bindings/l1block_deployed.go b/op-bindings/bindings/l1block_deployed.go index b7668c7a54b45..aa1eb067b9583 100644 --- a/op-bindings/bindings/l1block_deployed.go +++ b/op-bindings/bindings/l1block_deployed.go @@ -2,4 +2,4 @@ // This file is a generated binding and any manual changes will be lost. package bindings -var L1BlockDeployedBin = "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c806364ca23ef1161005b57806364ca23ef146100bc5780638381f58a146100fd578063b80777ea14610111578063e591b2821461013157600080fd5b8063042c2f571461008257806309bd5a60146100975780635cf24969146100b3575b600080fd5b6100956100903660046101f6565b610171565b005b6100a060025481565b6040519081526020015b60405180910390f35b6100a060015481565b6000546100e490700100000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100aa565b6000546100e49067ffffffffffffffff1681565b6000546100e49068010000000000000000900467ffffffffffffffff1681565b61014c73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100aa565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146101be576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60801b60409390931b90931791909117600055600155600255565b803567ffffffffffffffff811681146101f157600080fd5b919050565b600080600080600060a0868803121561020e57600080fd5b610217866101d9565b9450610225602087016101d9565b93506040860135925060608601359150610241608087016101d9565b9050929550929590935056fea164736f6c634300080a000a" +var L1BlockDeployedBin = "0x608060405234801561001057600080fd5b50600436106100885760003560e01c806364ca23ef1161005b57806364ca23ef146100d05780638381f58a14610111578063b80777ea14610125578063e591b2821461014557600080fd5b8063042c2f571461008d57806309bd5a60146100a25780635cf24969146100be5780635f528dc3146100c7575b600080fd5b6100a061009b366004610365565b610185565b005b6100ab60035481565b6040519081526020015b60405180910390f35b6100ab60015481565b6100ab60025481565b6000546100f890700100000000000000000000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100b5565b6000546100f89067ffffffffffffffff1681565b6000546100f89068010000000000000000900467ffffffffffffffff1681565b61016073deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146101d2576040517fce8c104800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608081901b604085901b8617176000819055600184905560038390556101f784610202565b600255505050505050565b600061021060025483610216565b92915050565b60008061023c84610237676124fee993bc0000678ac7230489e80000610286565b6102a2565b9050600061025e846102376729a2241af62c0000678ac7230489e80000610286565b9050670de0b6b3a764000061027383836102f3565b61027d91906103eb565b95945050505050565b600061029b83670de0b6b3a764000084610329565b9392505050565b6000826102b157506000610210565b828202828482816102c4576102c46103bc565b041461029b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915050610210565b60008282018381101561029b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff915050610210565b82820281151584158583048514171661034157600080fd5b0492915050565b803567ffffffffffffffff8116811461036057600080fd5b919050565b600080600080600060a0868803121561037d57600080fd5b61038686610348565b945061039460208701610348565b935060408601359250606086013591506103b060808701610348565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610421577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c634300080a000a" diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index 17a4fe42e7d45..6e9783bd3a5b1 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -3,7 +3,7 @@ DeployerWhitelist_Test:test_owner() (gas: 7647) DeployerWhitelist_Test:test_storageSlots() (gas: 33483) GasPriceOracle_Test:test_baseFee() (gas: 8395) GasPriceOracle_Test:test_gasPrice() (gas: 8384) -GasPriceOracle_Test:test_l1BaseFee() (gas: 10626) +GasPriceOracle_Test:test_l1BaseFee() (gas: 11373) GasPriceOracle_Test:test_onlyOwnerSetDecimals() (gas: 10575) GasPriceOracle_Test:test_onlyOwnerSetOverhead() (gas: 10599) GasPriceOracle_Test:test_onlyOwnerSetScalar() (gas: 10640) @@ -14,12 +14,13 @@ GasPriceOracle_Test:test_setL1BaseFeeReverts() (gas: 11658) GasPriceOracle_Test:test_setOverhead() (gas: 36767) GasPriceOracle_Test:test_setScalar() (gas: 36840) GasPriceOracle_Test:test_storageLayout() (gas: 86683) -L1BlockTest:test_basefee() (gas: 7575) +L1BlockTest:test_averageBasefee() (gas: 7946) +L1BlockTest:test_basefee() (gas: 7553) L1BlockTest:test_hash() (gas: 7552) L1BlockTest:test_number() (gas: 7651) -L1BlockTest:test_sequenceNumber() (gas: 7596) +L1BlockTest:test_sequenceNumber() (gas: 7661) L1BlockTest:test_timestamp() (gas: 7683) -L1BlockTest:test_updateValues() (gas: 23144) +L1BlockTest:test_updateValues() (gas: 46016) L1BlockNumberTest:test_fallback() (gas: 10755) L1BlockNumberTest:test_getL1BlockNumber() (gas: 10589) L1BlockNumberTest:test_receive() (gas: 17418) diff --git a/packages/contracts-bedrock/contracts/L2/GasPriceOracle.sol b/packages/contracts-bedrock/contracts/L2/GasPriceOracle.sol index 12fafd0619a13..164a40e6a72c8 100644 --- a/packages/contracts-bedrock/contracts/L2/GasPriceOracle.sol +++ b/packages/contracts-bedrock/contracts/L2/GasPriceOracle.sol @@ -68,7 +68,7 @@ contract GasPriceOracle is Ownable { } function l1BaseFee() public view returns (uint256) { - return L1Block(Lib_PredeployAddresses.L1_BLOCK_ATTRIBUTES).basefee(); + return L1Block(Lib_PredeployAddresses.L1_BLOCK_ATTRIBUTES).averageBasefee(); } /** diff --git a/packages/contracts-bedrock/contracts/L2/L1Block.sol b/packages/contracts-bedrock/contracts/L2/L1Block.sol index 9dfb4d04793aa..4635f944c4ae6 100644 --- a/packages/contracts-bedrock/contracts/L2/L1Block.sol +++ b/packages/contracts-bedrock/contracts/L2/L1Block.sol @@ -1,6 +1,8 @@ //SPDX-License-Identifier: MIT pragma solidity 0.8.10; +import { Lib_FeeSmoothing } from "../libraries/Lib_FeeSmoothing.sol"; + /** * @title L1Block * @dev This is an L2 predeploy contract that holds values from the L1 @@ -40,6 +42,11 @@ contract L1Block { */ uint256 public basefee; + /** + * @notice The average L1 basefee + */ + uint256 public averageBasefee; + /** * @notice The latest L1 blockhash */ @@ -75,5 +82,15 @@ contract L1Block { sstore(basefee.slot, _basefee) sstore(hash.slot, _hash) } + + averageBasefee = _nextAverageBasefee(_basefee); + } + + /** + * @notice Compute the running average L1 basefee + */ + + function _nextAverageBasefee(uint256 _basefee) internal returns (uint256) { + return Lib_FeeSmoothing.rollingAverage(averageBasefee, _basefee); } } diff --git a/packages/contracts-bedrock/contracts/libraries/Lib_FeeSmoothing.sol b/packages/contracts-bedrock/contracts/libraries/Lib_FeeSmoothing.sol new file mode 100644 index 0000000000000..ed4ce7dcd9e46 --- /dev/null +++ b/packages/contracts-bedrock/contracts/libraries/Lib_FeeSmoothing.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol"; + +/** + * @title Lib_FeeSmoothing + */ +library Lib_FeeSmoothing { + /** + * @notice Weight applied to average + */ + uint256 constant internal prevWeight = 7e18; + + /** + * @notice Weight applied to value being added to average + */ + uint256 constant internal nextWeight = 3e18; + + /** + * @notice Computes a rolling average + */ + function rollingAverage( + uint256 prev, + uint256 next + ) internal returns (uint256) { + uint256 a = saturatingMul(prev, FixedPointMathLib.divWadDown(prevWeight, 1e19)); + uint256 b = saturatingMul(next, FixedPointMathLib.divWadDown(nextWeight, 1e19)); + return saturatingAdd(a, b) / 1e18; + } + + /** + * @notice Saturating multiplication + */ + function saturatingMul(uint256 a, uint256 b) internal returns (uint256) { + unchecked { + if (a == 0) { + return 0; + } + uint256 c = a * b; + if (c / a != b) { + return type(uint256).max; + } + return c; + } + } + + /** + * @notice Saturating addition + */ + function saturatingAdd(uint256 a, uint256 b) internal returns (uint256) { + unchecked { + uint256 c = a + b; + if (c < a) { + return type(uint256).max; + } + return c; + } + } +} diff --git a/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol b/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol index 6c053e74aedb9..7424d00f913eb 100644 --- a/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol +++ b/packages/contracts-bedrock/contracts/test/GasPriceOracle.t.sol @@ -5,6 +5,7 @@ import { CommonTest } from "./CommonTest.t.sol"; import { GasPriceOracle } from "../L2/GasPriceOracle.sol"; import { L1Block } from "../L2/L1Block.sol"; import { Lib_PredeployAddresses } from "../libraries/Lib_PredeployAddresses.sol"; +import { Lib_FeeSmoothing } from "../libraries/Lib_FeeSmoothing.sol"; contract GasPriceOracle_Test is CommonTest { @@ -81,7 +82,8 @@ contract GasPriceOracle_Test is CommonTest { function test_l1BaseFee() external { uint256 l1BaseFee = gasOracle.l1BaseFee(); - assertEq(l1BaseFee, 100); + uint256 expect = Lib_FeeSmoothing.rollingAverage(0, 100); + assertEq(l1BaseFee, expect); } function test_gasPrice() external { diff --git a/packages/contracts-bedrock/contracts/test/L1Block.t.sol b/packages/contracts-bedrock/contracts/test/L1Block.t.sol index d89d18fa3577f..63e07cd666551 100644 --- a/packages/contracts-bedrock/contracts/test/L1Block.t.sol +++ b/packages/contracts-bedrock/contracts/test/L1Block.t.sol @@ -3,12 +3,15 @@ pragma solidity 0.8.10; import { CommonTest } from "./CommonTest.t.sol"; import { L1Block } from "../L2/L1Block.sol"; +import { Lib_FeeSmoothing } from "../libraries/Lib_FeeSmoothing.sol"; contract L1BlockTest is CommonTest { L1Block lb; address depositor; bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1)); + uint256 averageBasefee; + function setUp() external { lb = new L1Block(); depositor = lb.DEPOSITOR_ACCOUNT(); @@ -17,11 +20,14 @@ contract L1BlockTest is CommonTest { } function test_updatesValues(uint64 n, uint64 t, uint256 b, bytes32 h, uint64 s) external { + averageBasefee = Lib_FeeSmoothing.rollingAverage(averageBasefee, b); + vm.prank(depositor); lb.setL1BlockValues(n, t, b, h, s); assertEq(lb.number(), n); assertEq(lb.timestamp(), t); assertEq(lb.basefee(), b); + assertEq(lb.averageBasefee(), averageBasefee); assertEq(lb.hash(), h); assertEq(lb.sequenceNumber(), s); } @@ -38,6 +44,11 @@ contract L1BlockTest is CommonTest { assertEq(lb.basefee(), 3); } + function test_averageBasefee() external { + uint256 expect = Lib_FeeSmoothing.rollingAverage(0, 3); + assertEq(lb.averageBasefee(), expect); + } + function test_hash() external { assertEq(lb.hash(), NON_ZERO_HASH); } diff --git a/packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol b/packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol index f9f252642142a..1f8ed4f308fbe 100644 --- a/packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol +++ b/packages/contracts-bedrock/contracts/test/Lib_RLP.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Unlicense pragma solidity >=0.8.0; -import {Bytes32AddressLib} from "solmate/utils/Bytes32AddressLib.sol"; +import {Bytes32AddressLib} from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol"; // prettier-ignore library LibRLP { diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 700a32a448bb1..895d1e125c0d1 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -7,8 +7,7 @@ optimizer_runs = 999999 remappings = [ '@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/', '@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/', - 'excessively-safe-call/=node_modules/excessively-safe-call/src/', - 'solmate/=node_modules/@rari-capital/solmate/src', + '@rari-capital/solmate/=node_modules/@rari-capital/solmate', 'forge-std/=node_modules/forge-std/src', 'ds-test/=node_modules/ds-test/src' ]