diff --git a/.env.example b/.env.example index bfab354ce..0f59595b6 100644 --- a/.env.example +++ b/.env.example @@ -27,4 +27,5 @@ BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/XXXXXXXX ETHERSCAN_API_KEY=XXXXXXXX POLYGONSCAN_API_KEY=XXXXXXXX -BSCSCAN_API_KEY=XXXXXXXX \ No newline at end of file +BSCSCAN_API_KEY=XXXXXXXX +ARBISCAN_API_KEY=XXXXXXXX \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9cbdca9b7..35d3fe011 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,7 +73,7 @@ jobs: echo "✅ Passed" >> $GITHUB_STEP_SUMMARY tests: - needs: ["lint", "build"] + needs: ["build"] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/LICENSE b/LICENSE index 3f19c92f6..11b0fd732 100644 --- a/LICENSE +++ b/LICENSE @@ -9,14 +9,10 @@ Parameters Licensor: Fastlane Labs -Licensed Work: FastLane Protocol - The Licensed Work is (c) 2023 Fastlane Labs +Licensed Work: Atlas Protocol + The Licensed Work is (c) 2024 Fastlane Labs -Additional Use Grant: Any uses listed and defined at - fastlane-protocol-license.fastlane.finance - -Change Date: The earlier of 2025-07-01 or a date specified at - fastlane-protocol-license.fastlane.finance +Change Date: 2026-07-01 Change License: GNU General Public License v2.0 or later diff --git a/deployments.json b/deployments.json index 1c309dfd4..b99161227 100644 --- a/deployments.json +++ b/deployments.json @@ -18,10 +18,10 @@ "FL_ONLINE_DAPP_CONTROL": "0xf0E388C7DFfE14a61280a4E5b84d77be3d2875e3" }, "POLYGON": { - "ATLAS": "0x912AceADa1b9c9B378894D0610C5684167710FDD", - "ATLAS_VERIFICATION": "0x2fBF38a38D753E4ce398000CCC552Efa50702e1e", - "SIMULATOR": "0x1244E4B8D93D2A72692Bf3600f7f5a494e24895a", - "SORTER": "0xFac7bf300E7eb17A2eD0Be67b60f5FeDd2E28E90", + "ATLAS": "0xB363f4D32DdB0b43622eA07Ae9145726941272B4", + "ATLAS_VERIFICATION": "0x621c6970fD9F124230feE35117d318069056819a", + "SIMULATOR": "0x82A3460920582968688FD887F21c5F3155A3BBd4", + "SORTER": "0xf8Bd19064A77297A691a29d9a40dF76F32fc86ad", "FL_ONLINE_DAPP_CONTROL": "0x498aC70345AD6b161eEf4AFBEA8F010401cfa780" }, "BSC": { @@ -54,6 +54,13 @@ "SORTER": "0x81b2a2eD250fFF6808C54B46d519C9491E822F09", "L2_GAS_CALCULATOR": "0x7AcE2aC844F4104f86a2A04010C1b1e3f5d43196" }, + "ARBITRUM": { + "ATLAS": "0xf0E388C7DFfE14a61280a4E5b84d77be3d2875e3", + "ATLAS_VERIFICATION": "0xD72D821dA82964c0546a5501347a3959808E072f", + "SIMULATOR": "0xae631aCDC436b9Dfd75C5629F825330d91459445", + "SORTER": "0xb47387995e866908B25b49e8BaC7e499170461A6", + "L2_GAS_CALCULATOR": "0xAb665f032e6A20Ef7D43FfD4E92a2f4fd6d5771e" + }, "MAINNET": { "ATLAS": "", "ATLAS_VERIFICATION": "", diff --git a/foundry.toml b/foundry.toml index fdbb6ebe5..217b928a2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,7 +5,7 @@ block_gas_limit = 300000000 gas_limit = 3000000000 gas_price = 1500000000 - solc_version = "0.8.25" + solc_version = "0.8.28" evm_version = "cancun" isolate = false gas_reports = ["Atlas", "AtlasVerification", "Simulator", "Sorter", "ExecutionEnvironment"] diff --git a/lib/forge-std b/lib/forge-std index beb836e33..5a802d7c1 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit beb836e33f9a207f4927abb7cd09ad0afe4b3f9f +Subproject commit 5a802d7c10abb4bbfb3e7214c75052ef9e6a06f8 diff --git a/lib/nitro-contracts b/lib/nitro-contracts index c60b18dc7..fbbcef09c 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit c60b18dc7cf7d1809616d737e9061f3ecc9f28a6 +Subproject commit fbbcef09c95f69decabaced3da683f987902f3e2 diff --git a/lib/solady b/lib/solady index 362b2efd2..7deab021a 160000 --- a/lib/solady +++ b/lib/solady @@ -1 +1 @@ -Subproject commit 362b2efd20f38aea7252b391e5e016633ff79641 +Subproject commit 7deab021af0426307ae79d091c4d1e26e9e89cf0 diff --git a/package.json b/package.json index 9b3e5d9b7..b7eefc2d5 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "deploy-atlas-polygon": "source .env && forge script script/deploy-atlas.s.sol:DeployAtlasScript --rpc-url ${POLYGON_RPC_URL} --legacy --broadcast --etherscan-api-key ${POLYGONSCAN_API_KEY} --verify --delay 30", "deploy-atlas-arbitrum-sepolia": "source .env && forge script script/deploy-atlas.s.sol:DeployAtlasScript --rpc-url ${ARBITRUM_SEPOLIA_RPC_URL} --broadcast --etherscan-api-key ${ARBISCAN_API_KEY} --verify --delay 30", + "deploy-atlas-arbitrum": "source .env && forge script script/deploy-atlas.s.sol:DeployAtlasScript --rpc-url ${ARBITRUM_RPC_URL} --broadcast --etherscan-api-key ${ARBISCAN_API_KEY} --verify --delay 30", "deploy-fl-online-amoy": "source .env && forge script script/deploy-fl-online-control.s.sol:DeployFLOnlineControlScript --rpc-url ${AMOY_RPC_URL} --broadcast --etherscan-api-key ${POLYGONSCAN_API_KEY} --verify", "deploy-fl-online-polygon": "source .env && forge script script/deploy-fl-online-control.s.sol:DeployFLOnlineControlScript --rpc-url ${POLYGON_RPC_URL} --broadcast --etherscan-api-key ${POLYGONSCAN_API_KEY} --verify", @@ -62,6 +63,8 @@ "solver-deposit": "source .env && forge script script/solver-deposit.s.sol:SolverAtlasDepositScript --fork-url http://localhost:8545 --broadcast --non-interactive", "setup-demo": "npm run deploy-atlas-swap-intent-tx-builder && npm run deploy-solver && npm run solver-deposit", + "deploy-gas-calculator-base": "source .env && forge script script/deploy-gas-calculator.s.sol:DeployGasCalculatorScript --rpc-url ${BASE_RPC_URL} --broadcast --etherscan-api-key ${ETHERSCAN_API_KEY} --verify", + "atlas-addr": "echo 'ATLAS:' && jq -r '.ATLAS' deployments.json", "swap-intent-addr": "echo 'SWAP INTENT DAPP CONTROL:' && jq -r '.SWAP_INTENT_DAPP_CONTROL' deployments.json", "tx-builder-addr": "echo 'TX BUILDER:' && jq -r '.TX_BUILDER' deployments.json", diff --git a/script/base/deploy-base.s.sol b/script/base/deploy-base.s.sol index 8b7dbea0c..26b2b0aff 100644 --- a/script/base/deploy-base.s.sol +++ b/script/base/deploy-base.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; @@ -7,15 +7,15 @@ import "forge-std/StdJson.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { SwapIntentDAppControl } from "src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { Simulator } from "src/contracts/helpers/Simulator.sol"; -import { Sorter } from "src/contracts/helpers/Sorter.sol"; -import { SimpleRFQSolver } from "test/SwapIntent.t.sol"; +import { Atlas } from "../../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../../src/contracts/atlas/AtlasVerification.sol"; +import { SwapIntentDAppControl } from "../../src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; +import { TxBuilder } from "../../src/contracts/helpers/TxBuilder.sol"; +import { Simulator } from "../../src/contracts/helpers/Simulator.sol"; +import { Sorter } from "../../src/contracts/helpers/Sorter.sol"; +import { SimpleRFQSolver } from "../../test/SwapIntent.t.sol"; -import { Utilities } from "src/contracts/helpers/Utilities.sol"; +import { Utilities } from "../../src/contracts/helpers/Utilities.sol"; contract DeployBaseScript is Script { using stdJson for string; @@ -72,6 +72,19 @@ contract DeployBaseScript is Script { } } + function _getSurchargeRates() internal view returns (uint256 atlasSurchargeRate, uint256 bundlerSurchargeRate) { + uint256 chainId = block.chainid; + if (chainId == 137 || chainId == 80_002) { + // POLYGON and AMOY + atlasSurchargeRate = 5_000_000; // 50% + bundlerSurchargeRate = 5_000_000; // 50% + } else { + // Default - for all other chains + atlasSurchargeRate = 1_000_000; // 10% + bundlerSurchargeRate = 1_000_000; // 10% + } + } + // NOTE: When handling JSON with StdJson, prefix keys with '.' e.g. '.ATLAS' // These 2 functions abstract away the '.' thing though. // Pass in a key like 'ATLAS', and the current chain will be detected via `block.chainid` in `_getDeployChain()` @@ -85,7 +98,14 @@ contract DeployBaseScript is Script { // console.log("Getting", fullKey, "from deployments.json"); - // NOTE: Use fullKey method above for safety + // Revert if key doesn't exist in JSON. + if (!json.keyExists(fullKey)) revert(string.concat(fullKey, " not found in deployments.json")); + + // If key exists but is empty, return address(0) + address decodedAddr = abi.decode(json.parseRaw(fullKey), (address)); + if (decodedAddr == address(0x20) || decodedAddr == address(0)) return address(0); + + // Otherwise, return the address return json.readAddress(fullKey); } diff --git a/script/create-oev-demo-positions.s.sol b/script/create-oev-demo-positions.s.sol index 3c6761701..be10a6bcf 100644 --- a/script/create-oev-demo-positions.s.sol +++ b/script/create-oev-demo-positions.s.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; import { DeployBaseScript } from "script/base/deploy-base.s.sol"; -import { ChainlinkDAppControl } from "src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; -import { ChainlinkAtlasWrapper } from "src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; +import { ChainlinkDAppControl } from "../src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; +import { ChainlinkAtlasWrapper } from "../src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; -import { Token } from "src/contracts/helpers/DemoToken.sol"; -import { DemoLendingProtocol } from "src/contracts/helpers/DemoLendingProtocol.sol"; +import { Token } from "../src/contracts/helpers/DemoToken.sol"; +import { DemoLendingProtocol } from "../src/contracts/helpers/DemoLendingProtocol.sol"; // Sets up a few liquidatable positions in the Lending Protocol. ETH for gas fees distributed by Lending Gov. contract CreateOEVDemoPositionsScript is DeployBaseScript { diff --git a/script/deploy-atlas.s.sol b/script/deploy-atlas.s.sol index 631de34f3..5f53b7b56 100644 --- a/script/deploy-atlas.s.sol +++ b/script/deploy-atlas.s.sol @@ -1,20 +1,25 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; -import { DeployGasCalculatorScript } from "script/deploy-gas-calculator.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; +import { GasCalculatorDeployHelper } from "./deploy-gas-calculator.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { Simulator } from "src/contracts/helpers/Simulator.sol"; -import { Sorter } from "src/contracts/helpers/Sorter.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; +import { FactoryLib } from "../src/contracts/atlas/FactoryLib.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; +import { Simulator } from "../src/contracts/helpers/Simulator.sol"; +import { Sorter } from "../src/contracts/helpers/Sorter.sol"; +import { ExecutionEnvironment } from "../src/contracts/common/ExecutionEnvironment.sol"; + +contract DeployAtlasScript is DeployBaseScript, GasCalculatorDeployHelper { + uint256 ESCROW_DURATION = 64; + uint256 ATLAS_SURCHARGE_RATE; // Set below + uint256 BUNDLER_SURCHARGE_RATE; // Set below -contract DeployAtlasScript is DeployBaseScript { function run() external { console.log("\n=== DEPLOYING Atlas ===\n"); @@ -23,19 +28,16 @@ contract DeployAtlasScript is DeployBaseScript { uint256 deployerPrivateKey = vm.envUint("GOV_PRIVATE_KEY"); address deployer = vm.addr(deployerPrivateKey); - // Computes the addresses at which contracts will be deployed - address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 1); - address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); - address expectedSimulatorAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 3); + (ATLAS_SURCHARGE_RATE, BUNDLER_SURCHARGE_RATE) = _getSurchargeRates(); - // Deploy gas calculator for Arbitrum chains after other deployments - address l2GasCalculatorAddr = address(0); - uint256 chainId = block.chainid; + // Computes the addresses at which AtlasVerification will be deployed + address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); + address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 3); + address expectedSimulatorAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 4); - if (chainId == 42_161 || chainId == 42_170 || chainId == 421_614) { - // Deploy gas calculator for Arbitrum chains - l2GasCalculatorAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 4); - } + // Deploy L2 Gas Calculator after other deployments + address expectedL2GasCalculatorAddr = _predictGasCalculatorAddress(deployer, vm.getNonce(deployer) + 5); + address actualL2GasCalculatorAddr; // Set below during deployment if chain is an L2 address prevSimAddr = _getAddressFromDeploymentsJson("SIMULATOR"); uint256 prevSimBalance = (prevSimAddr == address(0)) ? 0 : prevSimAddr.balance; @@ -47,17 +49,26 @@ contract DeployAtlasScript is DeployBaseScript { vm.startBroadcast(deployerPrivateKey); ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment(expectedAtlasAddr); + FactoryLib factoryLib = new FactoryLib(address(execEnvTemplate)); atlas = new Atlas({ - escrowDuration: 64, + escrowDuration: ESCROW_DURATION, + atlasSurchargeRate: ATLAS_SURCHARGE_RATE, + bundlerSurchargeRate: BUNDLER_SURCHARGE_RATE, verification: expectedAtlasVerificationAddr, simulator: expectedSimulatorAddr, - executionTemplate: address(execEnvTemplate), + factoryLib: address(factoryLib), initialSurchargeRecipient: deployer, - l2GasCalculator: l2GasCalculatorAddr // is 0 if not on Arbitrum + l2GasCalculator: expectedL2GasCalculatorAddr // address(0) if chain not an L2 }); atlasVerification = new AtlasVerification(address(atlas)); - simulator = new Simulator(); + + // If chain is an L2, expectedL2GasCalculatorAddr will be non-zero + if (expectedL2GasCalculatorAddr != address(0)) { + actualL2GasCalculatorAddr = _newGasCalculator(); + } + + // After predicted address deployments done, do other setup txs: simulator.setAtlas(address(atlas)); // If prev Simulator deployment has native assets, withdraw them to new Simulator @@ -65,15 +76,9 @@ contract DeployAtlasScript is DeployBaseScript { Simulator(payable(prevSimAddr)).withdrawETH(address(simulator)); } + // Sorter address not predicted or required in the other contracts, so deployed last. sorter = new Sorter(address(atlas)); - if (chainId == 42_161 || chainId == 42_170 || chainId == 421_614) { - // Deploy gas calculator for Arbitrum chains - console.log("Deploying L2 Gas Calculator at: ", l2GasCalculatorAddr); - DeployGasCalculatorScript gasCalculatorDeployer = new DeployGasCalculatorScript(); - l2GasCalculatorAddr = gasCalculatorDeployer.deployL2GasCalculator(); - } - vm.stopBroadcast(); bool error = false; @@ -122,6 +127,25 @@ contract DeployAtlasScript is DeployBaseScript { console.log("ERROR: Sorter deployment address is 0x0"); error = true; } + // Check FactoryLib address set correctly in Atlas + if (address(factoryLib) != atlas.FACTORY_LIB()) { + console.log("ERROR: FactoryLib address not set correctly in Atlas"); + error = true; + } + // Check ExecutionEnvironment address set correctly in FactoryLib + if (address(execEnvTemplate) != factoryLib.EXECUTION_ENV_TEMPLATE()) { + console.log("ERROR: ExecutionEnvironment address not set correctly in FactoryLib"); + error = true; + } + // Check L2 Gas Calculator address set correctly + if (actualL2GasCalculatorAddr != atlas.L2_GAS_CALCULATOR()) { + console.log("ERROR: L2 Gas Calculator address not set correctly in Atlas"); + error = true; + } + if (actualL2GasCalculatorAddr != expectedL2GasCalculatorAddr) { + console.log("ERROR: L2 Gas Calculator deployment address not as expected"); + error = true; + } // Check ESCROW_DURATION was not set to 0 if (atlas.ESCROW_DURATION() == 0) { console.log("ERROR: ESCROW_DURATION was set to 0"); @@ -137,8 +161,8 @@ contract DeployAtlasScript is DeployBaseScript { _writeAddressToDeploymentsJson("ATLAS_VERIFICATION", address(atlasVerification)); _writeAddressToDeploymentsJson("SIMULATOR", address(simulator)); _writeAddressToDeploymentsJson("SORTER", address(sorter)); - if (l2GasCalculatorAddr != address(0)) { - _writeAddressToDeploymentsJson("L2_GAS_CALCULATOR", l2GasCalculatorAddr); + if (actualL2GasCalculatorAddr != address(0)) { + _writeAddressToDeploymentsJson("L2_GAS_CALCULATOR", actualL2GasCalculatorAddr); } // Print the table header @@ -150,8 +174,8 @@ contract DeployAtlasScript is DeployBaseScript { console.log("| AtlasVerification | ", address(atlasVerification), " |"); console.log("| Simulator | ", address(simulator), " |"); console.log("| Sorter | ", address(sorter), " |"); - if (l2GasCalculatorAddr != address(0)) { - console.log("| L2 Gas Calculator | ", l2GasCalculatorAddr, " |"); + if (actualL2GasCalculatorAddr != address(0)) { + console.log("| L2 Gas Calculator | ", actualL2GasCalculatorAddr, " |"); } console.log("------------------------------------------------------------------------"); console.log("\n"); diff --git a/script/deploy-demo-tokens.s.sol b/script/deploy-demo-tokens.s.sol index b5517c645..3d24baca4 100644 --- a/script/deploy-demo-tokens.s.sol +++ b/script/deploy-demo-tokens.s.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; import { DeployBaseScript } from "script/base/deploy-base.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { V2RewardDAppControl } from "src/contracts/examples/v2-example-router/V2RewardDAppControl.sol"; -import { IUniswapV2Router02 } from "src/contracts/examples/v2-example-router/interfaces/IUniswapV2Router.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { V2RewardDAppControl } from "../src/contracts/examples/v2-example-router/V2RewardDAppControl.sol"; +import { IUniswapV2Router02 } from "../src/contracts/examples/v2-example-router/interfaces/IUniswapV2Router.sol"; -import { Token } from "src/contracts/helpers/DemoToken.sol"; +import { Token } from "../src/contracts/helpers/DemoToken.sol"; import { WETH } from "solady/tokens/WETH.sol"; // Deploy 3 stablecoin tokens (DAI, USDA, USDB) - all 18 decimals diff --git a/script/deploy-exec-env.s.sol b/script/deploy-exec-env.s.sol index 66cbf86a2..d603a180a 100644 --- a/script/deploy-exec-env.s.sol +++ b/script/deploy-exec-env.s.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; +import { ExecutionEnvironment } from "../src/contracts/common/ExecutionEnvironment.sol"; contract DeployExecEnvScript is DeployBaseScript { ExecutionEnvironment public execEnv; diff --git a/script/deploy-fl-online-control.s.sol b/script/deploy-fl-online-control.s.sol index 7ee4beeaa..ac9d9998a 100644 --- a/script/deploy-fl-online-control.s.sol +++ b/script/deploy-fl-online-control.s.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { FastLaneOnlineOuter } from "src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { FastLaneOnlineOuter } from "../src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol"; contract DeployFLOnlineControlScript is DeployBaseScript { FastLaneOnlineOuter flOnline; diff --git a/script/deploy-gas-calculator.s.sol b/script/deploy-gas-calculator.s.sol index b7be43f5b..93936b0a1 100644 --- a/script/deploy-gas-calculator.s.sol +++ b/script/deploy-gas-calculator.s.sol @@ -1,14 +1,72 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { DeployBaseScript } from "script/base/deploy-base.s.sol"; + import { ArbitrumGasCalculator } from "src/contracts/gasCalculator/ArbitrumGasCalculator.sol"; +import { BaseGasCalculator } from "src/contracts/gasCalculator/BaseGasCalculator.sol"; + +contract GasCalculatorDeployHelper is Test { + // NOTE: Adjust the constructor parameters as needed here: + // ----------------------------------------------------------------------------------------------- + // Base: + // ----------------------------------------------------------------------------------------------- + uint256 constant BASE_SEPOLIA = 8453; + uint256 constant BASE_MAINNET = 84_532; + address constant BASE_GAS_PRICE_ORACLE = address(0x420000000000000000000000000000000000000F); + int256 constant BASE_CALLDATA_LENGTH_OFFSET = 0; // can be negative or positive + // ----------------------------------------------------------------------------------------------- + // Arbitrum: + // ----------------------------------------------------------------------------------------------- + uint256 constant ARBITRUM_SEPOLIA = 421_614; + uint256 constant ARBITRUM_ONE = 42_161; + uint256 constant ARBITRUM_NOVA = 42_170; + int256 constant ARBITRUM_CALLDATA_LENGTH_OFFSET = 0; + // ----------------------------------------------------------------------------------------------- + + function _newGasCalculator() internal returns (address l2GasCalculatorAddr) { + uint256 chainId = block.chainid; + + if (chainId == BASE_MAINNET || chainId == BASE_SEPOLIA) { + // Base + BaseGasCalculator gasCalculator = new BaseGasCalculator({ + gasPriceOracle: BASE_GAS_PRICE_ORACLE, + calldataLenOffset: BASE_CALLDATA_LENGTH_OFFSET + }); + l2GasCalculatorAddr = address(gasCalculator); + } else if (chainId == ARBITRUM_ONE || chainId == ARBITRUM_SEPOLIA || chainId == ARBITRUM_NOVA) { + // Arbitrum One or Arbitrum Sepolia + ArbitrumGasCalculator gasCalculator = new ArbitrumGasCalculator({ + calldataLenOffset: ARBITRUM_CALLDATA_LENGTH_OFFSET + }); + l2GasCalculatorAddr = address(gasCalculator); + } else { + revert("Error: Chain ID not supported for L2 Gas Calculator deployment"); + } + } -contract DeployGasCalculatorScript is DeployBaseScript { - int256 private constant ARBITRUM_CALLDATA_LENGTH_OFFSET = 0; + /// @notice Returns the predicted address of the gas calculator contract, given the nonce of the deployment tx. Or + /// returns address(0) if the current chain does not require an L2 Gas Calculator. + function _predictGasCalculatorAddress(address deployer, uint256 deployNonce) internal returns (address) { + if (_chainNeedsL2GasCalculator()) { + return vm.computeCreateAddress(deployer, deployNonce); + } + + // If not one of the supported chains above, return address(0) + return address(0); + } - function run() external returns (address) { + function _chainNeedsL2GasCalculator() internal returns (bool) { + uint256 chainId = block.chainid; + + return (chainId == BASE_MAINNET || chainId == BASE_SEPOLIA) + || (chainId == ARBITRUM_ONE || chainId == ARBITRUM_SEPOLIA || chainId == ARBITRUM_NOVA); + } +} + +contract DeployGasCalculatorScript is DeployBaseScript, GasCalculatorDeployHelper { + function run() external { console.log("\n=== DEPLOYING Gas Calculator ===\n"); console.log("Deploying to chain: \t\t", _getDeployChain()); @@ -18,43 +76,18 @@ contract DeployGasCalculatorScript is DeployBaseScript { console.log("Deployer address: \t\t", deployer); vm.startBroadcast(deployerPrivateKey); - address deploymentAddr = deployL2GasCalculator(); + address l2GasCalculatorAddr = _newGasCalculator(); vm.stopBroadcast(); - _writeAddressToDeploymentsJson("L2_GAS_CALCULATOR", deploymentAddr); + _writeAddressToDeploymentsJson("L2_GAS_CALCULATOR", l2GasCalculatorAddr); console.log("\n"); console.log("-------------------------------------------------------------------------------"); console.log("| Contract | Address |"); console.log("-------------------------------------------------------------------------------"); - console.log("| L2_GAS_CALCULATOR | ", deploymentAddr, " |"); + console.log("| L2_GAS_CALCULATOR | ", l2GasCalculatorAddr, " |"); console.log("-------------------------------------------------------------------------------"); console.log("\n"); console.log("You can find the contract address in deployments.json"); - - return deploymentAddr; - } - - function deployL2GasCalculator() public returns (address) { - uint256 chainId = block.chainid; - address deploymentAddr; - - if (chainId == 42_161 || chainId == 421_614) { - // Arbitrum One or Arbitrum Sepolia - ArbitrumGasCalculator gasCalculator = new ArbitrumGasCalculator({ - calldataLenOffset: ARBITRUM_CALLDATA_LENGTH_OFFSET, - _isArbitrumNova: false - }); - deploymentAddr = address(gasCalculator); - } else if (chainId == 42_170) { - // Arbitrum Nova - ArbitrumGasCalculator gasCalculator = - new ArbitrumGasCalculator({ calldataLenOffset: ARBITRUM_CALLDATA_LENGTH_OFFSET, _isArbitrumNova: true }); - deploymentAddr = address(gasCalculator); - } else { - revert("Error: Chain ID not supported for gas calculator deployment"); - } - - return deploymentAddr; } } diff --git a/script/deploy-oev-demo.s.sol b/script/deploy-oev-demo.s.sol index 13954c4d5..d48fd33ba 100644 --- a/script/deploy-oev-demo.s.sol +++ b/script/deploy-oev-demo.s.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { ChainlinkDAppControl } from "src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; -import { ChainlinkAtlasWrapper } from "src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { ChainlinkDAppControl } from "../src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; +import { ChainlinkAtlasWrapper } from "../src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; -import { Token } from "src/contracts/helpers/DemoToken.sol"; -import { DemoLendingProtocol } from "src/contracts/helpers/DemoLendingProtocol.sol"; +import { Token } from "../src/contracts/helpers/DemoToken.sol"; +import { DemoLendingProtocol } from "../src/contracts/helpers/DemoLendingProtocol.sol"; contract DeployOEVDemoScript is DeployBaseScript { address public constant CHAINLINK_ETH_USD = 0x694AA1769357215DE4FAC081bf1f309aDC325306; // on Sepolia diff --git a/script/deploy-solver.s.sol b/script/deploy-solver.s.sol index 499e6b733..12ef6c13e 100644 --- a/script/deploy-solver.s.sol +++ b/script/deploy-solver.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; diff --git a/script/deploy-sorter.s.sol b/script/deploy-sorter.s.sol index 0440ee64a..9d9c44c48 100644 --- a/script/deploy-sorter.s.sol +++ b/script/deploy-sorter.s.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { Sorter } from "src/contracts/helpers/Sorter.sol"; +import { Sorter } from "../src/contracts/helpers/Sorter.sol"; contract DeploySorterScript is DeployBaseScript { function run() external { diff --git a/script/deploy-swap-intent-control.s.sol b/script/deploy-swap-intent-control.s.sol index 6bf1c8d78..9e3b01eff 100644 --- a/script/deploy-swap-intent-control.s.sol +++ b/script/deploy-swap-intent-control.s.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { SwapIntentDAppControl } from "src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { Simulator } from "src/contracts/helpers/Simulator.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { SwapIntentDAppControl } from "../src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; +import { Simulator } from "../src/contracts/helpers/Simulator.sol"; contract DeploySwapIntentControlScript is DeployBaseScript { function run() external { diff --git a/script/deploy-tx-builder.s.sol b/script/deploy-tx-builder.s.sol index 4c648ea71..fe6a977a0 100644 --- a/script/deploy-tx-builder.s.sol +++ b/script/deploy-tx-builder.s.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { Simulator } from "src/contracts/helpers/Simulator.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; +import { Simulator } from "../src/contracts/helpers/Simulator.sol"; contract DeployTxBuilderScript is DeployBaseScript { function run() external { diff --git a/script/deploy-v2-reward-control.s.sol b/script/deploy-v2-reward-control.s.sol index 263e4bee8..2f6b348eb 100644 --- a/script/deploy-v2-reward-control.s.sol +++ b/script/deploy-v2-reward-control.s.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { V2RewardDAppControl } from "src/contracts/examples/v2-example-router/V2RewardDAppControl.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { V2RewardDAppControl } from "../src/contracts/examples/v2-example-router/V2RewardDAppControl.sol"; contract DeployV2RewardControlScript is DeployBaseScript { V2RewardDAppControl v2RewardControl; diff --git a/script/log-balances.s.sol b/script/log-balances.s.sol index a8de086b7..edbe43314 100644 --- a/script/log-balances.s.sol +++ b/script/log-balances.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; diff --git a/script/mint-demo-tokens.s.sol b/script/mint-demo-tokens.s.sol index 36a6d883a..b7c814c7e 100644 --- a/script/mint-demo-tokens.s.sol +++ b/script/mint-demo-tokens.s.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; -import { Token } from "src/contracts/helpers/DemoToken.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; +import { Token } from "../src/contracts/helpers/DemoToken.sol"; import { WETH } from "solady/tokens/WETH.sol"; contract MintDemoTokensScript is DeployBaseScript { diff --git a/script/set-oev-demo-signers.s.sol b/script/set-oev-demo-signers.s.sol index 22ccf327d..b88b19038 100644 --- a/script/set-oev-demo-signers.s.sol +++ b/script/set-oev-demo-signers.s.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { ChainlinkDAppControl } from "src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; -import { ChainlinkAtlasWrapper } from "src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; +import { ChainlinkDAppControl } from "../src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; +import { ChainlinkAtlasWrapper } from "../src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; -import { Token } from "src/contracts/helpers/DemoToken.sol"; -import { DemoLendingProtocol } from "src/contracts/helpers/DemoLendingProtocol.sol"; +import { Token } from "../src/contracts/helpers/DemoToken.sol"; +import { DemoLendingProtocol } from "../src/contracts/helpers/DemoLendingProtocol.sol"; // For the Chainlink OEV demo, when its difficult to find a real `transmit()` tx with a low enough ETH price. // We replace the real Sepolia Chainlink ETH/USD signers with a set of test signers, in ChainlinkDAppControl. diff --git a/script/solver-deposit.s.sol b/script/solver-deposit.s.sol index 9daa79492..57e10b008 100644 --- a/script/solver-deposit.s.sol +++ b/script/solver-deposit.s.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; import "forge-std/StdJson.sol"; -import { DeployBaseScript } from "script/base/deploy-base.s.sol"; +import { DeployBaseScript } from "./base/deploy-base.s.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; // NOTE: When handling JSON with StdJson, prefix keys with '.' e.g. '.ATLAS' diff --git a/src/contracts/atlas/AtlETH.sol b/src/contracts/atlas/AtlETH.sol index 5b27bf0d9..b9e2a8a0e 100644 --- a/src/contracts/atlas/AtlETH.sol +++ b/src/contracts/atlas/AtlETH.sol @@ -1,23 +1,34 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { SafeCast } from "openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import { Permit69 } from "src/contracts/atlas/Permit69.sol"; -import "src/contracts/types/EscrowTypes.sol"; + +import { SafeBlockNumber } from "../libraries/SafeBlockNumber.sol"; +import { Permit69 } from "./Permit69.sol"; +import "../types/EscrowTypes.sol"; /// @author FastLane Labs /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract AtlETH is Permit69 { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator ) - Permit69(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator) + Permit69( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator + ) { } /*////////////////////////////////////////////////////////////// diff --git a/src/contracts/atlas/Atlas.sol b/src/contracts/atlas/Atlas.sol index c17d08258..5635d17ab 100644 --- a/src/contracts/atlas/Atlas.sol +++ b/src/contracts/atlas/Atlas.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { LibSort } from "solady/utils/LibSort.sol"; @@ -7,19 +7,19 @@ import { LibSort } from "solady/utils/LibSort.sol"; import { Escrow } from "./Escrow.sol"; import { Factory } from "./Factory.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/ValidCalls.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/LockTypes.sol"; +import "../types/ConfigTypes.sol"; +import "../types/DAppOperation.sol"; +import "../types/ValidCalls.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; -import { IL2GasCalculator } from "src/contracts/interfaces/IL2GasCalculator.sol"; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import { SafetyBits } from "../libraries/SafetyBits.sol"; +import { IL2GasCalculator } from "../interfaces/IL2GasCalculator.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; -/// @title Atlas V1 +/// @title Atlas V1.1 /// @author FastLane Labs /// @notice The Execution Abstraction protocol. contract Atlas is Escrow, Factory { @@ -28,14 +28,24 @@ contract Atlas is Escrow, Factory { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator, - address executionTemplate + address factoryLib ) - Escrow(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator) - Factory(executionTemplate) + Escrow( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator + ) + Factory(factoryLib) { } /// @notice metacall is the entrypoint function for the Atlas transactions. @@ -361,7 +371,6 @@ contract Atlas is Escrow, Factory { uint32 callConfig ) internal - view override returns (bool) { diff --git a/src/contracts/atlas/AtlasVerification.sol b/src/contracts/atlas/AtlasVerification.sol index 77aa640c9..7dc847219 100644 --- a/src/contracts/atlas/AtlasVerification.sol +++ b/src/contracts/atlas/AtlasVerification.sol @@ -1,23 +1,23 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { EIP712 } from "openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol"; import { ECDSA } from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol"; import { SignatureChecker } from "openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol"; -import { DAppIntegration } from "src/contracts/atlas/DAppIntegration.sol"; -import { NonceManager } from "src/contracts/atlas/NonceManager.sol"; - -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { AtlasConstants } from "src/contracts/types/AtlasConstants.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/ValidCalls.sol"; +import { DAppIntegration } from "./DAppIntegration.sol"; +import { NonceManager } from "./NonceManager.sol"; + +import { SafeBlockNumber } from "../libraries/SafeBlockNumber.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import { CallVerification } from "../libraries/CallVerification.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; +import { AtlasConstants } from "../types/AtlasConstants.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import "../types/DAppOperation.sol"; +import "../types/EscrowTypes.sol"; +import "../types/ValidCalls.sol"; /// @title AtlasVerification /// @author FastLane Labs diff --git a/src/contracts/atlas/DAppIntegration.sol b/src/contracts/atlas/DAppIntegration.sol index 4542c0a3d..447a1c863 100644 --- a/src/contracts/atlas/DAppIntegration.sol +++ b/src/contracts/atlas/DAppIntegration.sol @@ -1,11 +1,11 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; +import { AtlasEvents } from "../types/AtlasEvents.sol"; /// @title DAppIntegration /// @author FastLane Labs diff --git a/src/contracts/atlas/Escrow.sol b/src/contracts/atlas/Escrow.sol index 1e33ef1da..5b255a656 100644 --- a/src/contracts/atlas/Escrow.sol +++ b/src/contracts/atlas/Escrow.sol @@ -1,24 +1,24 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { AtlETH } from "./AtlETH.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ISolverContract } from "src/contracts/interfaces/ISolverContract.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; - -import { SafeCall } from "src/contracts/libraries/SafeCall/SafeCall.sol"; -import { EscrowBits } from "src/contracts/libraries/EscrowBits.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import { AccountingMath } from "src/contracts/libraries/AccountingMath.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; +import { IExecutionEnvironment } from "../interfaces/IExecutionEnvironment.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { ISolverContract } from "../interfaces/ISolverContract.sol"; +import { IAtlasVerification } from "../interfaces/IAtlasVerification.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; + +import { SafeCall } from "../libraries/SafeCall/SafeCall.sol"; +import { SafeBlockNumber } from "../libraries/SafeBlockNumber.sol"; +import { EscrowBits } from "../libraries/EscrowBits.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import { SafetyBits } from "../libraries/SafetyBits.sol"; +import { AccountingMath } from "../libraries/AccountingMath.sol"; +import { DAppConfig } from "../types/ConfigTypes.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/EscrowTypes.sol"; +import "../types/LockTypes.sol"; /// @title Escrow /// @author FastLane Labs @@ -32,12 +32,22 @@ abstract contract Escrow is AtlETH { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator ) - AtlETH(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator) + AtlETH( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator + ) { if (escrowDuration == 0) revert InvalidEscrowDuration(); } @@ -93,11 +103,16 @@ abstract contract Escrow is AtlETH { bool _success; bytes memory _data; + // Calculate gas limit ceiling, including gas to return gracefully even if userOp call is OOG. + uint256 _gasLimit = gasleft() * 63 / 64 - _GRACEFUL_RETURN_GAS_OFFSET; + // Use the smaller of userOp.gas and the gas limit ceiling + _gasLimit = userOp.gas < _gasLimit ? userOp.gas : _gasLimit; + if (!_borrow(userOp.value)) { revert InsufficientEscrow(); } - (_success, _data) = ctx.executionEnvironment.call{ value: userOp.value }( + (_success, _data) = ctx.executionEnvironment.call{ value: userOp.value, gas: _gasLimit }( abi.encodePacked( abi.encodeCall(IExecutionEnvironment.userWrapper, userOp), ctx.setAndPack(ExecutionPhase.UserOperation) ) @@ -111,6 +126,7 @@ abstract contract Escrow is AtlETH { return returnData; } } + // revert for failed if (ctx.isSimulation) revert UserOpSimFail(); revert UserOpFail(); @@ -191,7 +207,9 @@ abstract contract Escrow is AtlETH { if (_result.executionSuccessful()) { // First successful solver call that paid what it bid - emit SolverTxResult(solverOp.solver, solverOp.from, true, true, _result); + emit SolverTxResult( + solverOp.solver, solverOp.from, dConfig.to, solverOp.bidToken, bidAmount, true, true, _result + ); ctx.solverSuccessful = true; ctx.solverOutcome = uint24(_result); @@ -206,7 +224,16 @@ abstract contract Escrow is AtlETH { // Account for failed SolverOperation gas costs _handleSolverAccounting(solverOp, _gasWaterMark, _result, !prevalidated); - emit SolverTxResult(solverOp.solver, solverOp.from, _result.executedWithError(), false, _result); + emit SolverTxResult( + solverOp.solver, + solverOp.from, + dConfig.to, + solverOp.bidToken, + bidAmount, + _result.executedWithError(), + false, + _result + ); return 0; } @@ -564,8 +591,8 @@ abstract contract Escrow is AtlETH { bool _success; // Set the solver lock and solver address at the beginning to ensure reliability - _setSolverLock(uint256(uint160(solverOp.from))); - _setSolverTo(solverOp.solver); + t_solverLock = uint256(uint160(solverOp.from)); + t_solverTo = solverOp.solver; // ------------------------------------- // // Pre-Solver Call // @@ -611,8 +638,8 @@ abstract contract Escrow is AtlETH { solverOp.bidToken, bidAmount, solverOp.data, - // Only pass the returnData to solver if it came from userOp call and not from preOps call. - _activeCallConfig().needsUserReturnData() ? returnData : new bytes(0) + // Only pass the returnData (either from userOp or preOps) if the dApp requires it + _activeCallConfig().forwardReturnData() ? returnData : new bytes(0) ) ) ); diff --git a/src/contracts/atlas/Factory.sol b/src/contracts/atlas/Factory.sol index 76c819c76..e2f1dc6b9 100644 --- a/src/contracts/atlas/Factory.sol +++ b/src/contracts/atlas/Factory.sol @@ -1,29 +1,19 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { Mimic } from "src/contracts/common/Mimic.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import { FactoryLib } from "./FactoryLib.sol"; + +import { IDAppControl } from "../interfaces/IDAppControl.sol"; +import { DAppConfig } from "../types/ConfigTypes.sol"; +import { UserOperation } from "../types/UserOperation.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; -/// @title Factory -/// @author FastLane Labs -/// @notice Provides functionality for creating and managing execution environments for DApps within the Atlas Protocol. -/// @dev This contract uses deterministic deployment to generate and manage Execution Environment instances based on -/// predefined templates. abstract contract Factory { - address public immutable EXECUTION_ENV_TEMPLATE; + address public immutable FACTORY_LIB; bytes32 internal immutable _FACTORY_BASE_SALT; - /// @notice Initializes a new Factory contract instance by setting the immutable salt for deterministic deployment - /// of Execution Environments and storing the execution template address. - /// @dev The Execution Environment Template must be separately deployed using the same calculated salt. - /// @param executionTemplate Address of the pre-deployed execution template contract for creating Execution - /// Environment instances. - constructor(address executionTemplate) { - EXECUTION_ENV_TEMPLATE = executionTemplate; + constructor(address factoryLib) { + FACTORY_LIB = factoryLib; _FACTORY_BASE_SALT = keccak256(abi.encodePacked(block.chainid, address(this))); } @@ -57,7 +47,6 @@ abstract contract Factory { address control ) external - view returns (address executionEnvironment, uint32 callConfig, bool exists) { callConfig = IDAppControl(control).CALL_CONFIG(); @@ -100,25 +89,13 @@ abstract contract Factory { internal returns (address executionEnvironment) { - bytes memory _creationCode = _getMimicCreationCode({ user: user, control: control, callConfig: callConfig }); bytes32 _salt = _computeSalt(user, control, callConfig); - executionEnvironment = address( - uint160( - uint256( - keccak256( - abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(abi.encodePacked(_creationCode))) - ) - ) - ) + bytes memory returnData = _delegatecallFactoryLib( + abi.encodeCall(FactoryLib.getOrCreateExecutionEnvironment, (user, control, callConfig, _salt)) ); - if (executionEnvironment.code.length == 0) { - assembly { - executionEnvironment := create2(0, add(_creationCode, 32), mload(_creationCode), _salt) - } - emit AtlasEvents.ExecutionEnvironmentCreated(user, executionEnvironment); - } + return abi.decode(returnData, (address)); } /// @notice Generates the address of a user's execution environment affected by deprecated callConfig changes in the @@ -135,79 +112,28 @@ abstract contract Factory { uint32 callConfig ) internal - view returns (address executionEnvironment) { - bytes memory _creationCode = _getMimicCreationCode({ user: user, control: control, callConfig: callConfig }); bytes32 _salt = _computeSalt(user, control, callConfig); - executionEnvironment = address( - uint160( - uint256( - keccak256( - abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(abi.encodePacked(_creationCode))) - ) - ) - ) + bytes memory returnData = _delegatecallFactoryLib( + abi.encodeCall(FactoryLib.getExecutionEnvironmentCustom, (user, control, callConfig, _salt)) ); + + return abi.decode(returnData, (address)); } function _computeSalt(address user, address control, uint32 callConfig) internal view returns (bytes32) { return keccak256(abi.encodePacked(_FACTORY_BASE_SALT, user, control, callConfig)); } - /// @notice Generates the creation code for the execution environment contract. - /// @param control The address of the DAppControl contract associated with the execution environment. - /// @param callConfig The configuration flags defining the behavior of the execution environment. - /// @param user The address of the user for whom the execution environment is being created, contributing to the - /// uniqueness of the creation code. - /// @return creationCode The bytecode representing the creation code of the execution environment contract. - function _getMimicCreationCode( - address user, - address control, - uint32 callConfig - ) - internal - view - returns (bytes memory creationCode) - { - address _executionLib = EXECUTION_ENV_TEMPLATE; - // NOTE: Changing compiler settings or solidity versions can break this. - creationCode = type(Mimic).creationCode; - - assembly { - // Insert the ExecutionEnvironment "Lib" address, into the AAAA placeholder in the creation code. - mstore( - add(creationCode, 79), - or( - and(mload(add(creationCode, 79)), not(shl(96, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), - shl(96, _executionLib) - ) - ) - - // Insert the user address into the BBBB placeholder in the creation code. - mstore( - add(creationCode, 111), - or( - and(mload(add(creationCode, 111)), not(shl(96, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), - shl(96, user) - ) - ) - - // Insert the control address into the CCCC placeholder in the creation code. - mstore( - add(creationCode, 132), - or( - and(mload(add(creationCode, 132)), not(shl(96, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), - shl(96, control) - ) - ) - - // Insert the callConfig into the 2222 placeholder in the creation code. - mstore( - add(creationCode, 153), - or(and(mload(add(creationCode, 153)), not(shl(224, 0xFFFFFFFF))), shl(224, callConfig)) - ) + function _delegatecallFactoryLib(bytes memory data) internal returns (bytes memory) { + (bool _success, bytes memory _result) = FACTORY_LIB.delegatecall(data); + if (!_success) { + assembly { + revert(add(_result, 32), mload(_result)) + } } + return _result; } } diff --git a/src/contracts/atlas/FactoryLib.sol b/src/contracts/atlas/FactoryLib.sol new file mode 100644 index 000000000..a6b74e3d1 --- /dev/null +++ b/src/contracts/atlas/FactoryLib.sol @@ -0,0 +1,146 @@ +//SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.28; + +import { Mimic } from "../common/Mimic.sol"; +import { AtlasEvents } from "../types/AtlasEvents.sol"; + +// NOTE: Do not call these functions directly. This contract should only ever be delegatecalled by the Atlas contract. + +contract FactoryLib { + address public immutable EXECUTION_ENV_TEMPLATE; + + /// @notice Initializes a new Factory contract instance by setting the immutable salt for deterministic deployment + /// of Execution Environments and storing the execution template address. + /// @dev The Execution Environment Template must be separately deployed using the same calculated salt. + /// @param executionTemplate Address of the pre-deployed execution template contract for creating Execution + /// Environment instances. + constructor(address executionTemplate) { + EXECUTION_ENV_TEMPLATE = executionTemplate; + } + + /// @notice Deploys a new execution environment or retrieves the address of an existing one based on the DApp + /// control, user, and configuration. + /// @dev Uses the `create2` opcode for deterministic deployment, allowing the calculation of the execution + /// environment's address before deployment. The deployment uses a combination of the DAppControl address, user + /// address, call configuration, and a unique salt to ensure the uniqueness and predictability of the environment's + /// address. + /// @param user The address of the user for whom the execution environment is being set. + /// @param control The address of the DAppControl contract providing the operational context. + /// @param callConfig CallConfig settings of the DAppControl contract. + /// @return executionEnvironment The address of the newly created or already existing execution environment. + function getOrCreateExecutionEnvironment( + address user, + address control, + uint32 callConfig, + bytes32 salt + ) + public + payable + returns (address executionEnvironment) + { + bytes memory _creationCode = _getMimicCreationCode({ user: user, control: control, callConfig: callConfig }); + + executionEnvironment = address( + uint160( + uint256( + keccak256( + abi.encodePacked(bytes1(0xff), address(this), salt, keccak256(abi.encodePacked(_creationCode))) + ) + ) + ) + ); + + if (executionEnvironment.code.length == 0) { + assembly { + executionEnvironment := create2(0, add(_creationCode, 32), mload(_creationCode), salt) + } + emit AtlasEvents.ExecutionEnvironmentCreated(user, executionEnvironment); + } + } + + /// @notice Generates the address of a user's execution environment affected by deprecated callConfig changes in the + /// DAppControl. + /// @dev Calculates the deterministic address of the execution environment based on the user, control, + /// callConfig, and controlCodeHash, ensuring consistency across changes in callConfig. + /// @param user The address of the user for whom the execution environment's address is being generated. + /// @param control The address of the DAppControl contract associated with the execution environment. + /// @param callConfig The configuration flags defining the behavior of the execution environment. + /// @return executionEnvironment The address of the user's execution environment. + function getExecutionEnvironmentCustom( + address user, + address control, + uint32 callConfig, + bytes32 salt + ) + public + view + returns (address executionEnvironment) + { + bytes memory _creationCode = _getMimicCreationCode({ user: user, control: control, callConfig: callConfig }); + + executionEnvironment = address( + uint160( + uint256( + keccak256( + abi.encodePacked(bytes1(0xff), address(this), salt, keccak256(abi.encodePacked(_creationCode))) + ) + ) + ) + ); + } + + /// @notice Generates the creation code for the execution environment contract. + /// @param control The address of the DAppControl contract associated with the execution environment. + /// @param callConfig The configuration flags defining the behavior of the execution environment. + /// @param user The address of the user for whom the execution environment is being created, contributing to the + /// uniqueness of the creation code. + /// @return creationCode The bytecode representing the creation code of the execution environment contract. + function _getMimicCreationCode( + address user, + address control, + uint32 callConfig + ) + internal + view + returns (bytes memory creationCode) + { + address _executionLib = EXECUTION_ENV_TEMPLATE; + // NOTE: Changing compiler settings or solidity versions can break this. + creationCode = type(Mimic).creationCode; + + assembly { + // Insert the ExecutionEnvironment "Lib" address, into the AAAA placeholder in the creation code. + mstore( + add(creationCode, 79), + or( + and(mload(add(creationCode, 79)), not(shl(96, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), + shl(96, _executionLib) + ) + ) + + // Insert the user address into the BBBB placeholder in the creation code. + mstore( + add(creationCode, 111), + or( + and(mload(add(creationCode, 111)), not(shl(96, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), + shl(96, user) + ) + ) + + // Insert the control address into the CCCC placeholder in the creation code. + mstore( + add(creationCode, 132), + or( + and(mload(add(creationCode, 132)), not(shl(96, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))), + shl(96, control) + ) + ) + + // Insert the callConfig into the 2222 placeholder in the creation code. + mstore( + add(creationCode, 153), + or(and(mload(add(creationCode, 153)), not(shl(224, 0xFFFFFFFF))), shl(224, callConfig)) + ) + } + } +} diff --git a/src/contracts/atlas/GasAccounting.sol b/src/contracts/atlas/GasAccounting.sol index d8ef0f016..d2daa18c5 100644 --- a/src/contracts/atlas/GasAccounting.sol +++ b/src/contracts/atlas/GasAccounting.sol @@ -1,17 +1,18 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { SafeCast } from "openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; -import { SafetyLocks } from "src/contracts/atlas/SafetyLocks.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import { EscrowBits } from "src/contracts/libraries/EscrowBits.sol"; -import { AccountingMath } from "src/contracts/libraries/AccountingMath.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import { IL2GasCalculator } from "src/contracts/interfaces/IL2GasCalculator.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; + +import { SafetyLocks } from "./SafetyLocks.sol"; +import { SafeBlockNumber } from "../libraries/SafeBlockNumber.sol"; +import { EscrowBits } from "../libraries/EscrowBits.sol"; +import { AccountingMath } from "../libraries/AccountingMath.sol"; +import { SolverOperation } from "../types/SolverOperation.sol"; +import { DAppConfig } from "../types/ConfigTypes.sol"; +import { IL2GasCalculator } from "../interfaces/IL2GasCalculator.sol"; +import "../types/EscrowTypes.sol"; +import "../types/LockTypes.sol"; /// @title GasAccounting /// @author FastLane Labs @@ -22,12 +23,22 @@ abstract contract GasAccounting is SafetyLocks { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator ) - SafetyLocks(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator) + SafetyLocks( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator + ) { } /// @notice Sets the initial accounting values for the metacall transaction. @@ -36,19 +47,18 @@ abstract contract GasAccounting is SafetyLocks { uint256 _rawClaims = (FIXED_GAS_OFFSET + gasMarker) * tx.gasprice; // Set any withdraws or deposits - _setClaims(_rawClaims.withBundlerSurcharge()); + t_claims = _rawClaims.withSurcharge(BUNDLER_SURCHARGE_RATE); // Atlas surcharge is based on the raw claims value. - _setFees(_rawClaims.getAtlasSurcharge()); - _setDeposits(msg.value); - - // Explicitly set writeoffs and withdrawals to 0 in case multiple metacalls in single tx. - _setWriteoffs(0); - _setWithdrawals(0); + t_fees = _rawClaims.getSurcharge(ATLAS_SURCHARGE_RATE); + t_deposits = msg.value; - // Explicitly clear solverLock and solverTo in case multiple metacalls in single tx. - _setSolverLock(0); - _setSolverTo(address(0)); + // Explicitly set other transient vars to 0 in case multiple metacalls in single tx. + t_writeoffs = 0; + t_withdrawals = 0; + t_solverSurcharge = 0; + t_solverLock = 0; + t_solverTo = address(0); // The Lock slot is cleared at the end of the metacall, so no need to zero again here. } @@ -89,12 +99,12 @@ abstract contract GasAccounting is SafetyLocks { /// @return uint256 The current shortfall amount, or 0 if there is no shortfall. function shortfall() external view returns (uint256) { uint256 _currentDeficit = _deficit(); - uint256 _deposits = deposits(); + uint256 _deposits = t_deposits; return (_currentDeficit > _deposits) ? (_currentDeficit - _deposits) : 0; } function _deficit() internal view returns (uint256) { - return claims() + withdrawals() + fees() - writeoffs(); + return t_claims + t_withdrawals + t_fees - t_writeoffs; } /// @notice Allows a solver to settle any outstanding ETH owed, either to repay gas used by their solverOp or to @@ -117,7 +127,7 @@ abstract contract GasAccounting is SafetyLocks { // calls directly to the solver contract in this phase, the solver should be careful to not call malicious // contracts which may call reconcile() on their behalf, with an excessive maxApprovedGasSpend. if (_phase() != uint8(ExecutionPhase.SolverOperation)) revert WrongPhase(); - if (msg.sender != _solverTo()) revert InvalidAccess(); + if (msg.sender != t_solverTo) revert InvalidAccess(); (address _currentSolver, bool _calledBack, bool _fulfilled) = _solverLockData(); uint256 _bondedBalance = uint256(S_accessData[_currentSolver].bonded); @@ -126,12 +136,12 @@ abstract contract GasAccounting is SafetyLocks { if (maxApprovedGasSpend > _bondedBalance) maxApprovedGasSpend = _bondedBalance; uint256 _deductions = _deficit(); - uint256 _additions = deposits() + msg.value; + uint256 _additions = t_deposits + msg.value; // Add msg.value to solver's deposits // NOTE: Surplus deposits are credited back to the Solver during settlement. // NOTE: This function is called inside the solver try/catch and will be undone if solver fails. - if (msg.value > 0) _setDeposits(_additions); + if (msg.value > 0) t_deposits = _additions; // CASE: Callback verified but insufficient balance if (_deductions > _additions + maxApprovedGasSpend) { @@ -140,21 +150,21 @@ abstract contract GasAccounting is SafetyLocks { // but it does treat any msg.value as a deposit and allows for either the solver to call back with a // higher maxApprovedGasSpend or to have their deficit covered by a contribute during the postSolverOp // hook. - _setSolverLock(uint256(uint160(_currentSolver)) | _SOLVER_CALLED_BACK_MASK); + t_solverLock = (uint256(uint160(_currentSolver)) | _SOLVER_CALLED_BACK_MASK); } return _deductions - _additions; } // CASE: Callback verified and solver duty fulfilled if (!_fulfilled) { - _setSolverLock(uint256(uint160(_currentSolver)) | _SOLVER_CALLED_BACK_MASK | _SOLVER_FULFILLED_MASK); + t_solverLock = (uint256(uint160(_currentSolver)) | _SOLVER_CALLED_BACK_MASK | _SOLVER_FULFILLED_MASK); } return 0; } /// @notice Internal function to handle ETH contribution, increasing deposits if a non-zero value is sent. function _contribute() internal { - if (msg.value != 0) _setDeposits(deposits() + msg.value); + if (msg.value != 0) t_deposits += msg.value; } /// @notice Borrows ETH from the contract, transferring the specified amount to the caller if available. @@ -167,7 +177,7 @@ abstract contract GasAccounting is SafetyLocks { if (amount == 0) return true; if (address(this).balance < amount) return false; - _setWithdrawals(withdrawals() + amount); + t_withdrawals += amount; return true; } @@ -210,7 +220,7 @@ abstract contract GasAccounting is SafetyLocks { s_balanceOf[owner].unbonding = 0; _aData.bonded = 0; - _setWriteoffs(writeoffs() + deficit); + t_writeoffs += deficit; amount -= deficit; // Set amount equal to total to accurately track the changing bondedTotalSupply } else { // The unbonding balance is sufficient to cover the remaining amount owed. Draw everything from the @@ -231,7 +241,7 @@ abstract contract GasAccounting is SafetyLocks { S_accessData[owner] = _aData; S_bondedTotalSupply -= amount; - _setDeposits(deposits() + amount); + t_deposits += amount; } /// @notice Increases the owner's bonded balance by the specified amount. @@ -253,7 +263,7 @@ abstract contract GasAccounting is SafetyLocks { // Persist changes in the _aData memory struct back to storage S_accessData[owner] = _aData; - _setWithdrawals(withdrawals() + amount); + t_withdrawals += amount; } /// @notice Accounts for the gas cost of a failed SolverOperation, either by increasing writeoffs (if the bundler is @@ -282,16 +292,28 @@ abstract contract GasAccounting is SafetyLocks { if (result.bundlersFault()) { // CASE: Solver is not responsible for the failure of their operation, so we blame the bundler // and reduce the total amount refunded to the bundler - _setWriteoffs(writeoffs() + _gasUsed.withAtlasAndBundlerSurcharges()); + t_writeoffs += _gasUsed.withSurcharges(ATLAS_SURCHARGE_RATE, BUNDLER_SURCHARGE_RATE); } else { // CASE: Solver failed, so we calculate what they owe. - uint256 _gasUsedWithSurcharges = _gasUsed.withAtlasAndBundlerSurcharges(); - _assign(solverOp.from, _gasUsedWithSurcharges, _gasUsedWithSurcharges, false); + uint256 _gasUsedWithSurcharges = _gasUsed.withSurcharges(ATLAS_SURCHARGE_RATE, BUNDLER_SURCHARGE_RATE); + uint256 _surchargesOnly = _gasUsedWithSurcharges - _gasUsed; + + // In `_assign()`, the failing solver's bonded AtlETH balance is reduced by `_gasUsedWithSurcharges`. Any + // deficit from that operation is added to `writeoffs` and returned as `_assignDeficit` below. The portion + // that can be covered by the solver's AtlETH is added to `deposits`, to account that it has been paid. + uint256 _assignDeficit = _assign(solverOp.from, _gasUsedWithSurcharges, _gasUsedWithSurcharges, false); + + // We track the surcharges (in excess of deficit - so the actual AtlETH that can be collected) separately, + // so that in the event of no successful solvers, any `_assign()`ed surcharges can be attributed to an + // increase in Atlas' cumulative surcharge. + if (_surchargesOnly > _assignDeficit) { + t_solverSurcharge += (_surchargesOnly - _assignDeficit); + } } } function _writeOffBidFindGasCost(uint256 gasUsed) internal { - _setWriteoffs(writeoffs() + gasUsed.withAtlasAndBundlerSurcharges()); + t_writeoffs += gasUsed.withSurcharges(ATLAS_SURCHARGE_RATE, BUNDLER_SURCHARGE_RATE); } /// @param ctx Context struct containing relevant context information for the Atlas auction. @@ -320,30 +342,57 @@ abstract contract GasAccounting is SafetyLocks { ) { uint256 _surcharge = S_cumulativeSurcharge; - uint256 _fees = fees(); - adjustedWithdrawals = withdrawals(); - adjustedDeposits = deposits(); - adjustedClaims = claims(); - adjustedWriteoffs = writeoffs(); + adjustedWithdrawals = t_withdrawals; + adjustedDeposits = t_deposits; + adjustedClaims = t_claims; + adjustedWriteoffs = t_writeoffs; + uint256 _fees = t_fees; uint256 _gasLeft = gasleft(); // Hold this constant for the calculations // Estimate the unspent, remaining gas that the Solver will not be liable for. uint256 _gasRemainder = _gasLeft * tx.gasprice; - // Calculate the preadjusted netAtlasGasSurcharge - netAtlasGasSurcharge = _fees - _gasRemainder.getAtlasSurcharge(); - - adjustedClaims -= _gasRemainder.withBundlerSurcharge(); - adjustedWithdrawals += netAtlasGasSurcharge; - S_cumulativeSurcharge = _surcharge + netAtlasGasSurcharge; // Update the cumulative surcharge + adjustedClaims -= _gasRemainder.withSurcharge(BUNDLER_SURCHARGE_RATE); + + if (ctx.solverSuccessful) { + // If a solver was successful, calc the full Atlas gas surcharge on the gas cost of the entire metacall, and + // add it to withdrawals so that the cost is assigned to winning solver by the end of _settle(). This will + // be offset by any gas surcharge paid by failed solvers, which would have been added to deposits or + // writeoffs in _handleSolverAccounting(). As such, the winning solver does not pay for surcharge on the gas + // used by other solvers. + netAtlasGasSurcharge = _fees - _gasRemainder.getSurcharge(ATLAS_SURCHARGE_RATE); + adjustedWithdrawals += netAtlasGasSurcharge; + S_cumulativeSurcharge = _surcharge + netAtlasGasSurcharge; + } else { + // If no successful solvers, only collect partial surcharges from solver's fault failures (if any) + uint256 _solverSurcharge = t_solverSurcharge; + if (_solverSurcharge > 0) { + netAtlasGasSurcharge = _solverSurcharge.getPortionFromTotalSurcharge({ + targetSurchargeRate: ATLAS_SURCHARGE_RATE, + totalSurchargeRate: ATLAS_SURCHARGE_RATE + BUNDLER_SURCHARGE_RATE + }); + + // When no winning solvers, bundler max refund is 80% of metacall gas cost. The remaining 20% can be + // collected through storage refunds. Any excess bundler surcharge is instead taken as Atlas surcharge. + uint256 _bundlerSurcharge = _solverSurcharge - netAtlasGasSurcharge; + uint256 _maxBundlerRefund = adjustedClaims.withoutSurcharge(BUNDLER_SURCHARGE_RATE).maxBundlerRefund(); + if (_bundlerSurcharge > _maxBundlerRefund) { + netAtlasGasSurcharge += _bundlerSurcharge - _maxBundlerRefund; + } + + adjustedWithdrawals += netAtlasGasSurcharge; + S_cumulativeSurcharge = _surcharge + netAtlasGasSurcharge; + } + return (adjustedWithdrawals, adjustedDeposits, adjustedClaims, adjustedWriteoffs, netAtlasGasSurcharge); + } // Calculate whether or not the bundler used an excessive amount of gas and, if so, reduce their // gas rebate. By reducing the claims, solvers end up paying less in total. if (ctx.solverCount > 0) { // Calculate the unadjusted bundler gas surcharge - uint256 _grossBundlerGasSurcharge = adjustedClaims.withoutBundlerSurcharge(); + uint256 _grossBundlerGasSurcharge = adjustedClaims.withoutSurcharge(BUNDLER_SURCHARGE_RATE); // Calculate an estimate for how much gas should be remaining // NOTE: There is a free buffer of one SolverOperation because solverIndex starts at 0. @@ -407,6 +456,8 @@ abstract contract GasAccounting is SafetyLocks { if (ctx.solverSuccessful && _winningSolver != ctx.bundler) { _amountSolverPays += _adjustedClaims; claimsPaidToBundler = _adjustedClaims; + } else if (_winningSolver == ctx.bundler) { + claimsPaidToBundler = 0; } else { claimsPaidToBundler = 0; _winningSolver = ctx.bundler; @@ -481,6 +532,6 @@ abstract contract GasAccounting is SafetyLocks { /// correct. /// @return True if the balance is reconciled, false otherwise. function _isBalanceReconciled() internal view returns (bool) { - return deposits() >= _deficit(); + return t_deposits >= _deficit(); } } diff --git a/src/contracts/atlas/NonceManager.sol b/src/contracts/atlas/NonceManager.sol index c4cb745ba..3f1b9a38c 100644 --- a/src/contracts/atlas/NonceManager.sol +++ b/src/contracts/atlas/NonceManager.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { AtlasConstants } from "src/contracts/types/AtlasConstants.sol"; +import { AtlasConstants } from "../types/AtlasConstants.sol"; contract NonceManager is AtlasConstants { // address => last used sequential nonce diff --git a/src/contracts/atlas/Permit69.sol b/src/contracts/atlas/Permit69.sol index 6d6f7d0ba..096d7630c 100644 --- a/src/contracts/atlas/Permit69.sol +++ b/src/contracts/atlas/Permit69.sol @@ -1,13 +1,14 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { GasAccounting } from "src/contracts/atlas/GasAccounting.sol"; -import { SAFE_USER_TRANSFER, SAFE_DAPP_TRANSFER } from "src/contracts/libraries/SafetyBits.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; +import { GasAccounting } from "./GasAccounting.sol"; + +import { SAFE_USER_TRANSFER, SAFE_DAPP_TRANSFER } from "../libraries/SafetyBits.sol"; +import "../types/LockTypes.sol"; +import "../types/EscrowTypes.sol"; // NOTE: Permit69 only works inside of the Atlas environment - specifically // inside of the custom ExecutionEnvironments that each user deploys when @@ -26,12 +27,22 @@ import "src/contracts/types/EscrowTypes.sol"; abstract contract Permit69 is GasAccounting { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator ) - GasAccounting(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator) + GasAccounting( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator + ) { } /// @notice Verifies that the caller is an authorized Execution Environment contract. diff --git a/src/contracts/atlas/SafetyLocks.sol b/src/contracts/atlas/SafetyLocks.sol index 2b3d66b92..87f274eea 100644 --- a/src/contracts/atlas/SafetyLocks.sol +++ b/src/contracts/atlas/SafetyLocks.sol @@ -1,13 +1,13 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { Storage } from "./Storage.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import "../types/EscrowTypes.sol"; +import "../types/LockTypes.sol"; /// @title SafetyLocks /// @author FastLane Labs @@ -18,12 +18,22 @@ abstract contract SafetyLocks is Storage { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator ) - Storage(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator) + Storage( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator + ) { } /// @notice Sets the Atlas lock to the specified execution environment. diff --git a/src/contracts/atlas/Storage.sol b/src/contracts/atlas/Storage.sol index 4a20052b1..baca20ae2 100644 --- a/src/contracts/atlas/Storage.sol +++ b/src/contracts/atlas/Storage.sol @@ -1,14 +1,14 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/libraries/AccountingMath.sol"; +import "../types/EscrowTypes.sol"; +import "../types/LockTypes.sol"; +import "../libraries/AccountingMath.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { AtlasConstants } from "src/contracts/types/AtlasConstants.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; +import { AtlasEvents } from "../types/AtlasEvents.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; +import { AtlasConstants } from "../types/AtlasConstants.sol"; +import { IAtlasVerification } from "../interfaces/IAtlasVerification.sol"; /// @title Storage /// @author FastLane Labs @@ -18,6 +18,8 @@ contract Storage is AtlasEvents, AtlasErrors, AtlasConstants { address public immutable SIMULATOR; address public immutable L2_GAS_CALCULATOR; uint256 public immutable ESCROW_DURATION; + uint256 public immutable ATLAS_SURCHARGE_RATE; + uint256 public immutable BUNDLER_SURCHARGE_RATE; // AtlETH public constants // These constants double as interface functions for the ERC20 standard, hence the lowercase naming convention. @@ -26,20 +28,21 @@ contract Storage is AtlasEvents, AtlasErrors, AtlasConstants { uint8 public constant decimals = 18; // Gas Accounting public constants - uint256 public constant ATLAS_SURCHARGE_RATE = AccountingMath._ATLAS_SURCHARGE_RATE; - uint256 public constant BUNDLER_SURCHARGE_RATE = AccountingMath._BUNDLER_SURCHARGE_RATE; uint256 public constant SCALE = AccountingMath._SCALE; uint256 public constant FIXED_GAS_OFFSET = AccountingMath._FIXED_GAS_OFFSET; // Transient storage slots - bytes32 private constant _T_LOCK_SLOT = keccak256("ATLAS_LOCK"); - bytes32 private constant _T_SOLVER_LOCK_SLOT = keccak256("ATLAS_SOLVER_LOCK"); - bytes32 private constant _T_SOLVER_TO_SLOT = keccak256("ATLAS_SOLVER_TO"); - bytes32 private constant _T_CLAIMS_SLOT = keccak256("ATLAS_CLAIMS"); - bytes32 private constant _T_FEES_SLOT = keccak256("ATLAS_FEES"); - bytes32 private constant _T_WRITEOFFS_SLOT = keccak256("ATLAS_WRITEOFFS"); - bytes32 private constant _T_WITHDRAWALS_SLOT = keccak256("ATLAS_WITHDRAWALS"); - bytes32 private constant _T_DEPOSITS_SLOT = keccak256("ATLAS_DEPOSITS"); + uint256 internal transient t_lock; // contains activeAddress, callConfig, and phase + uint256 internal transient t_solverLock; + address internal transient t_solverTo; // current solverOp.solver contract address + + // solverSurcharge = total surcharge collected from failed solverOps due to solver fault. + uint256 internal transient t_solverSurcharge; + uint256 internal transient t_claims; + uint256 internal transient t_fees; + uint256 internal transient t_writeoffs; + uint256 internal transient t_withdrawals; + uint256 internal transient t_deposits; // AtlETH storage uint256 internal S_totalSupply; @@ -56,6 +59,8 @@ contract Storage is AtlasEvents, AtlasErrors, AtlasConstants { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, @@ -67,6 +72,8 @@ contract Storage is AtlasEvents, AtlasErrors, AtlasConstants { SIMULATOR = simulator; L2_GAS_CALCULATOR = l2GasCalculator; ESCROW_DURATION = escrowDuration; + ATLAS_SURCHARGE_RATE = atlasSurchargeRate; + BUNDLER_SURCHARGE_RATE = bundlerSurchargeRate; // Gas Accounting // Initialized with msg.value to seed flash loan liquidity @@ -149,46 +156,26 @@ contract Storage is AtlasEvents, AtlasErrors, AtlasConstants { // Transient Internal Getters // // ---------------------------------------------------- // - function claims() internal view returns (uint256) { - return uint256(_tload(_T_CLAIMS_SLOT)); - } - - function fees() internal view returns (uint256) { - return uint256(_tload(_T_FEES_SLOT)); - } - - function writeoffs() internal view returns (uint256) { - return uint256(_tload(_T_WRITEOFFS_SLOT)); - } - - function withdrawals() internal view returns (uint256) { - return uint256(_tload(_T_WITHDRAWALS_SLOT)); - } - - function deposits() internal view returns (uint256) { - return uint256(_tload(_T_DEPOSITS_SLOT)); - } - function _lock() internal view returns (address activeEnvironment, uint32 callConfig, uint8 phase) { - bytes32 _lockData = _tload(_T_LOCK_SLOT); - activeEnvironment = address(uint160(uint256(_lockData >> 40))); - callConfig = uint32(uint256(_lockData >> 8)); - phase = uint8(uint256(_lockData)); + uint256 _lockData = t_lock; + activeEnvironment = address(uint160(_lockData >> 40)); + callConfig = uint32(_lockData >> 8); + phase = uint8(_lockData); } function _activeEnvironment() internal view returns (address) { // right shift 40 bits to remove the callConfig and phase, only activeEnvironment remains - return address(uint160(uint256(_tload(_T_LOCK_SLOT) >> 40))); + return address(uint160(t_lock >> 40)); } function _activeCallConfig() internal view returns (uint32) { // right shift 8 bits to remove the phase, cast to uint32 to remove the activeEnvironment - return uint32(uint256(_tload(_T_LOCK_SLOT) >> 8)); + return uint32(t_lock >> 8); } function _phase() internal view returns (uint8) { // right-most 8 bits of Lock are the phase - return uint8(uint256(_tload(_T_LOCK_SLOT))); + return uint8(t_lock); } /// @notice Returns information about the current state of the solver lock. @@ -196,18 +183,14 @@ contract Storage is AtlasEvents, AtlasErrors, AtlasConstants { /// @return calledBack Boolean indicating whether the solver has called back via `reconcile`. /// @return fulfilled Boolean indicating whether the solver's outstanding debt has been repaid via `reconcile`. function _solverLockData() internal view returns (address currentSolver, bool calledBack, bool fulfilled) { - uint256 _solverLock = uint256(_tload(_T_SOLVER_LOCK_SLOT)); + uint256 _solverLock = t_solverLock; currentSolver = address(uint160(_solverLock)); calledBack = _solverLock & _SOLVER_CALLED_BACK_MASK != 0; fulfilled = _solverLock & _SOLVER_FULFILLED_MASK != 0; } - function _solverTo() internal view returns (address) { - return address(uint160(uint256(_tload(_T_SOLVER_TO_SLOT)))); - } - function _isUnlocked() internal view returns (bool) { - return _tload(_T_LOCK_SLOT) == bytes32(_UNLOCKED); + return t_lock == _UNLOCKED; } // ---------------------------------------------------- // @@ -218,64 +201,15 @@ contract Storage is AtlasEvents, AtlasErrors, AtlasConstants { // Pack the lock slot from the right: // [ 56 bits ][ 160 bits ][ 32 bits ][ 8 bits ] // [ unused bits ][ activeEnvironment ][ callConfig ][ phase ] - _tstore( - _T_LOCK_SLOT, - bytes32(uint256(uint160(activeEnvironment))) << 40 | bytes32(uint256(callConfig)) << 8 - | bytes32(uint256(phase)) - ); + t_lock = uint256(uint160(activeEnvironment)) << 40 | uint256(callConfig) << 8 | uint256(phase); } function _releaseLock() internal { - _tstore(_T_LOCK_SLOT, bytes32(_UNLOCKED)); + t_lock = _UNLOCKED; } // Sets the Lock phase without changing the activeEnvironment or callConfig. function _setLockPhase(uint8 newPhase) internal { - _tstore(_T_LOCK_SLOT, (_tload(_T_LOCK_SLOT) & _LOCK_PHASE_MASK) | bytes32(uint256(newPhase))); - } - - function _setSolverLock(uint256 newSolverLock) internal { - _tstore(_T_SOLVER_LOCK_SLOT, bytes32(newSolverLock)); - } - - function _setSolverTo(address newSolverTo) internal { - _tstore(_T_SOLVER_TO_SLOT, bytes32(uint256(uint160(newSolverTo)))); - } - - function _setClaims(uint256 newClaims) internal { - _tstore(_T_CLAIMS_SLOT, bytes32(newClaims)); - } - - function _setFees(uint256 newFees) internal { - _tstore(_T_FEES_SLOT, bytes32(newFees)); - } - - function _setWriteoffs(uint256 newWriteoffs) internal { - _tstore(_T_WRITEOFFS_SLOT, bytes32(newWriteoffs)); - } - - function _setWithdrawals(uint256 newWithdrawals) internal { - _tstore(_T_WITHDRAWALS_SLOT, bytes32(newWithdrawals)); - } - - function _setDeposits(uint256 newDeposits) internal { - _tstore(_T_DEPOSITS_SLOT, bytes32(newDeposits)); - } - - // ------------------------------------------------------ // - // Transient Storage Helpers // - // ------------------------------------------------------ // - - function _tstore(bytes32 slot, bytes32 value) internal { - assembly { - tstore(slot, value) - } - } - - function _tload(bytes32 slot) internal view returns (bytes32 value) { - assembly { - value := tload(slot) - } - return value; + t_lock = (t_lock & _LOCK_PHASE_MASK) | uint256(newPhase); } } diff --git a/src/contracts/common/ExecutionBase.sol b/src/contracts/common/ExecutionBase.sol index 9a27878af..a1383ae9e 100644 --- a/src/contracts/common/ExecutionBase.sol +++ b/src/contracts/common/ExecutionBase.sol @@ -1,14 +1,15 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ExecutionPhase } from "src/contracts/types/LockTypes.sol"; -import { SAFE_USER_TRANSFER, SAFE_DAPP_TRANSFER } from "src/contracts/libraries/SafetyBits.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import "src/contracts/types/SolverOperation.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; + +import { ExecutionPhase } from "../types/LockTypes.sol"; +import { SAFE_USER_TRANSFER, SAFE_DAPP_TRANSFER } from "../libraries/SafetyBits.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; +import "../types/SolverOperation.sol"; contract Base { address public immutable ATLAS; diff --git a/src/contracts/common/ExecutionEnvironment.sol b/src/contracts/common/ExecutionEnvironment.sol index b818e2c22..84fb2fc03 100644 --- a/src/contracts/common/ExecutionEnvironment.sol +++ b/src/contracts/common/ExecutionEnvironment.sol @@ -1,19 +1,19 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { Base } from "src/contracts/common/ExecutionBase.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ISolverContract } from "src/contracts/interfaces/ISolverContract.sol"; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; +import { Base } from "./ExecutionBase.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/EscrowTypes.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { ISolverContract } from "../interfaces/ISolverContract.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/EscrowTypes.sol"; /// @title ExecutionEnvironment /// @author FastLane Labs diff --git a/src/contracts/common/Mimic.sol b/src/contracts/common/Mimic.sol index a88446bc9..ad7f4a718 100644 --- a/src/contracts/common/Mimic.sol +++ b/src/contracts/common/Mimic.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; contract Mimic { /* diff --git a/src/contracts/dapp/ControlTemplate.sol b/src/contracts/dapp/ControlTemplate.sol index df402abcf..3663f915e 100644 --- a/src/contracts/dapp/ControlTemplate.sol +++ b/src/contracts/dapp/ControlTemplate.sol @@ -1,10 +1,10 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; abstract contract DAppControlTemplate { uint32 internal constant DEFAULT_SOLVER_GAS_LIMIT = 1_000_000; diff --git a/src/contracts/dapp/DAppControl.sol b/src/contracts/dapp/DAppControl.sol index 6cf5fa25d..8340bd7f4 100644 --- a/src/contracts/dapp/DAppControl.sol +++ b/src/contracts/dapp/DAppControl.sol @@ -1,18 +1,18 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { DAppControlTemplate } from "./ControlTemplate.sol"; -import { ExecutionBase } from "src/contracts/common/ExecutionBase.sol"; -import { ExecutionPhase } from "src/contracts/types/LockTypes.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ValidCallsResult } from "src/contracts/types/ValidCalls.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; +import { ExecutionBase } from "../common/ExecutionBase.sol"; +import { ExecutionPhase } from "../types/LockTypes.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; +import { AtlasEvents } from "../types/AtlasEvents.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { ValidCallsResult } from "../types/ValidCalls.sol"; +import { IAtlasVerification } from "../interfaces/IAtlasVerification.sol"; /// @title DAppControl /// @author FastLane Labs diff --git a/src/contracts/examples/ex-post-mev-example/V2ExPost.sol b/src/contracts/examples/ex-post-mev-example/V2ExPost.sol index 43fe41498..993d023d9 100644 --- a/src/contracts/examples/ex-post-mev-example/V2ExPost.sol +++ b/src/contracts/examples/ex-post-mev-example/V2ExPost.sol @@ -1,22 +1,22 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Base Imports -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; +import { SafetyBits } from "../../libraries/SafetyBits.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; // Uni V2 Imports import { IUniswapV2Pair } from "./interfaces/IUniswapV2Pair.sol"; diff --git a/src/contracts/examples/fastlane-online/BaseStorage.sol b/src/contracts/examples/fastlane-online/BaseStorage.sol index d552082ea..457b564a5 100644 --- a/src/contracts/examples/fastlane-online/BaseStorage.sol +++ b/src/contracts/examples/fastlane-online/BaseStorage.sol @@ -1,9 +1,9 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/SolverOperation.sol"; +import "../../types/SolverOperation.sol"; -import { Reputation } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; +import { Reputation } from "./FastLaneTypes.sol"; contract BaseStorage { error FLOnline_NotUnlocked(); diff --git a/src/contracts/examples/fastlane-online/FastLaneControl.sol b/src/contracts/examples/fastlane-online/FastLaneControl.sol index 0166f2d6e..183e6c350 100644 --- a/src/contracts/examples/fastlane-online/FastLaneControl.sol +++ b/src/contracts/examples/fastlane-online/FastLaneControl.sol @@ -1,21 +1,21 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; - -import { SwapIntent, BaselineCall } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; -import { FastLaneOnlineErrors } from "src/contracts/examples/fastlane-online/FastLaneOnlineErrors.sol"; -import { IFastLaneOnline } from "src/contracts/examples/fastlane-online/IFastLaneOnline.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; + +import { SwapIntent, BaselineCall } from "./FastLaneTypes.sol"; +import { FastLaneOnlineErrors } from "./FastLaneOnlineErrors.sol"; +import { IFastLaneOnline } from "./IFastLaneOnline.sol"; interface ISolverGateway { function getBidAmount(bytes32 solverOpHash) external view returns (uint256 bidAmount); diff --git a/src/contracts/examples/fastlane-online/FastLaneOnlineErrors.sol b/src/contracts/examples/fastlane-online/FastLaneOnlineErrors.sol index 603cdff3a..436bb994a 100644 --- a/src/contracts/examples/fastlane-online/FastLaneOnlineErrors.sol +++ b/src/contracts/examples/fastlane-online/FastLaneOnlineErrors.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; contract FastLaneOnlineErrors { // FastLaneControl.sol diff --git a/src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol b/src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol index 08d35946d..b49f1f55d 100644 --- a/src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol +++ b/src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol @@ -1,27 +1,27 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { DAppOperation } from "src/contracts/types/DAppOperation.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { DAppOperation } from "../../types/DAppOperation.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Interface Import -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IAtlasVerification } from "../../interfaces/IAtlasVerification.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; -import { FastLaneOnlineControl } from "src/contracts/examples/fastlane-online/FastLaneControl.sol"; -import { BaseStorage } from "src/contracts/examples/fastlane-online/BaseStorage.sol"; +import { FastLaneOnlineControl } from "./FastLaneControl.sol"; +import { BaseStorage } from "./BaseStorage.sol"; -import { SwapIntent, BaselineCall } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; +import { SwapIntent, BaselineCall } from "./FastLaneTypes.sol"; interface IGeneralizedBackrunProxy { function getUser() external view returns (address); diff --git a/src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol b/src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol index bae46e1c5..fb4f10f65 100644 --- a/src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol +++ b/src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol @@ -1,28 +1,28 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { DAppOperation } from "src/contracts/types/DAppOperation.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { DAppOperation } from "../../types/DAppOperation.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Interface Import -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IAtlasVerification } from "../../interfaces/IAtlasVerification.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; -import { FastLaneOnlineControl } from "src/contracts/examples/fastlane-online/FastLaneControl.sol"; -import { FastLaneOnlineInner } from "src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol"; -import { SolverGateway } from "src/contracts/examples/fastlane-online/SolverGateway.sol"; +import { FastLaneOnlineControl } from "./FastLaneControl.sol"; +import { FastLaneOnlineInner } from "./FastLaneOnlineInner.sol"; +import { SolverGateway } from "./SolverGateway.sol"; -import { SwapIntent, BaselineCall } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; +import { SwapIntent, BaselineCall } from "./FastLaneTypes.sol"; contract FastLaneOnlineOuter is SolverGateway { constructor(address atlas, address protocolGuildWallet) SolverGateway(atlas, protocolGuildWallet) { } diff --git a/src/contracts/examples/fastlane-online/FastLaneTypes.sol b/src/contracts/examples/fastlane-online/FastLaneTypes.sol index 13e4270f8..786e6a7e3 100644 --- a/src/contracts/examples/fastlane-online/FastLaneTypes.sol +++ b/src/contracts/examples/fastlane-online/FastLaneTypes.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // External representation of the swap intent struct SwapIntent { diff --git a/src/contracts/examples/fastlane-online/IFastLaneOnline.sol b/src/contracts/examples/fastlane-online/IFastLaneOnline.sol index 412ab2935..df5d056d5 100644 --- a/src/contracts/examples/fastlane-online/IFastLaneOnline.sol +++ b/src/contracts/examples/fastlane-online/IFastLaneOnline.sol @@ -1,9 +1,9 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import { SwapIntent, BaselineCall, Reputation } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import { SwapIntent, BaselineCall, Reputation } from "./FastLaneTypes.sol"; interface IFastLaneOnline { // User entrypoint diff --git a/src/contracts/examples/fastlane-online/OuterHelpers.sol b/src/contracts/examples/fastlane-online/OuterHelpers.sol index ba2b78615..976674c2f 100644 --- a/src/contracts/examples/fastlane-online/OuterHelpers.sol +++ b/src/contracts/examples/fastlane-online/OuterHelpers.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; @@ -7,24 +7,24 @@ import { LibSort } from "solady/utils/LibSort.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { DAppOperation } from "src/contracts/types/DAppOperation.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { DAppOperation } from "../../types/DAppOperation.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; +import "../../types/EscrowTypes.sol"; // Interface Import -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ISimulator } from "src/contracts/interfaces/ISimulator.sol"; +import { IAtlasVerification } from "../../interfaces/IAtlasVerification.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; +import { ISimulator } from "../../interfaces/ISimulator.sol"; -import { FastLaneOnlineControl } from "src/contracts/examples/fastlane-online/FastLaneControl.sol"; -import { FastLaneOnlineInner } from "src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol"; +import { FastLaneOnlineControl } from "./FastLaneControl.sol"; +import { FastLaneOnlineInner } from "./FastLaneOnlineInner.sol"; -import { SwapIntent, BaselineCall, Reputation } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; +import { SwapIntent, BaselineCall, Reputation } from "./FastLaneTypes.sol"; contract OuterHelpers is FastLaneOnlineInner { // NOTE: Any funds collected in excess of the therapy bills required for the Cardano engineering team diff --git a/src/contracts/examples/fastlane-online/SolverGateway.sol b/src/contracts/examples/fastlane-online/SolverGateway.sol index 23178b690..a5a40f26d 100644 --- a/src/contracts/examples/fastlane-online/SolverGateway.sol +++ b/src/contracts/examples/fastlane-online/SolverGateway.sol @@ -1,30 +1,30 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { DAppOperation } from "src/contracts/types/DAppOperation.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { SafeBlockNumber } from "../../libraries/SafeBlockNumber.sol"; +import { DAppOperation } from "../../types/DAppOperation.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; +import "../../types/EscrowTypes.sol"; // Interface Import -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ISimulator } from "src/contracts/interfaces/ISimulator.sol"; +import { IAtlasVerification } from "../../interfaces/IAtlasVerification.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; +import { ISimulator } from "../../interfaces/ISimulator.sol"; -import { FastLaneOnlineControl } from "src/contracts/examples/fastlane-online/FastLaneControl.sol"; -import { OuterHelpers } from "src/contracts/examples/fastlane-online/OuterHelpers.sol"; +import { FastLaneOnlineControl } from "./FastLaneControl.sol"; +import { OuterHelpers } from "./OuterHelpers.sol"; -import { SwapIntent, BaselineCall, Reputation } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; +import { SwapIntent, BaselineCall, Reputation } from "./FastLaneTypes.sol"; contract SolverGateway is OuterHelpers { uint256 public constant USER_GAS_BUFFER = 350_000; diff --git a/src/contracts/examples/gas-filler/Filler.sol b/src/contracts/examples/gas-filler/Filler.sol index a0e9ee643..29f042c33 100644 --- a/src/contracts/examples/gas-filler/Filler.sol +++ b/src/contracts/examples/gas-filler/Filler.sol @@ -1,22 +1,22 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; // Atlas Base Imports -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; +import { SafetyBits } from "../../libraries/SafetyBits.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; interface IERC20 { function allowance(address owner, address spender) external view returns (uint256); diff --git a/src/contracts/examples/generalized-backrun/GeneralizedBackrunUserBundler.sol b/src/contracts/examples/generalized-backrun/GeneralizedBackrunUserBundler.sol index 6ae07c1d3..643fe0bea 100644 --- a/src/contracts/examples/generalized-backrun/GeneralizedBackrunUserBundler.sol +++ b/src/contracts/examples/generalized-backrun/GeneralizedBackrunUserBundler.sol @@ -1,22 +1,22 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { DAppOperation } from "src/contracts/types/DAppOperation.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { DAppOperation } from "../../types/DAppOperation.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Interface Import -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IAtlasVerification } from "../../interfaces/IAtlasVerification.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; struct Approval { address token; diff --git a/src/contracts/examples/intents-example/StateIntent.sol b/src/contracts/examples/intents-example/StateIntent.sol index 37a2e24b8..bc3984d81 100644 --- a/src/contracts/examples/intents-example/StateIntent.sol +++ b/src/contracts/examples/intents-example/StateIntent.sol @@ -1,15 +1,15 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Atlas Base Imports -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; +import { SafetyBits } from "../../libraries/SafetyBits.sol"; -import "src/contracts/types/LockTypes.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; import "forge-std/Test.sol"; diff --git a/src/contracts/examples/intents-example/SwapIntentDAppControl.sol b/src/contracts/examples/intents-example/SwapIntentDAppControl.sol index 8aabc1b1c..fd98fd9fa 100644 --- a/src/contracts/examples/intents-example/SwapIntentDAppControl.sol +++ b/src/contracts/examples/intents-example/SwapIntentDAppControl.sol @@ -1,16 +1,16 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; struct Condition { address antecedent; diff --git a/src/contracts/examples/intents-example/SwapIntentInvertBidDAppControl.sol b/src/contracts/examples/intents-example/SwapIntentInvertBidDAppControl.sol index 48b72c81d..3fc659dab 100644 --- a/src/contracts/examples/intents-example/SwapIntentInvertBidDAppControl.sol +++ b/src/contracts/examples/intents-example/SwapIntentInvertBidDAppControl.sol @@ -6,15 +6,15 @@ import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Base Imports -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; import "forge-std/Test.sol"; diff --git a/src/contracts/examples/intents-example/V4SwapIntent.sol b/src/contracts/examples/intents-example/V4SwapIntent.sol index 46c6f2775..519b5947f 100644 --- a/src/contracts/examples/intents-example/V4SwapIntent.sol +++ b/src/contracts/examples/intents-example/V4SwapIntent.sol @@ -6,15 +6,15 @@ import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Base Imports -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; import "forge-std/Test.sol"; diff --git a/src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol b/src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol index 5fb5df22c..daf3d5dd7 100644 --- a/src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol +++ b/src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol @@ -1,13 +1,10 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; import { SafeERC20, IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import { - IChainlinkAtlasWrapper, - AggregatorV2V3Interface -} from "src/contracts/examples/oev-example/IChainlinkAtlasWrapper.sol"; -import { IChainlinkDAppControl } from "src/contracts/examples/oev-example/IChainlinkDAppControl.sol"; +import { IChainlinkAtlasWrapper, AggregatorV2V3Interface } from "./IChainlinkAtlasWrapper.sol"; +import { IChainlinkDAppControl } from "./IChainlinkDAppControl.sol"; // A wrapper contract for a specific Chainlink price feed, used by Atlas to capture Oracle Extractable Value (OEV). // Each MEV-generating protocol needs their own wrapper for each Chainlink price feed they use. diff --git a/src/contracts/examples/oev-example/ChainlinkAtlasWrapperAlt.sol b/src/contracts/examples/oev-example/ChainlinkAtlasWrapperAlt.sol index 47cefee0d..ed3842065 100644 --- a/src/contracts/examples/oev-example/ChainlinkAtlasWrapperAlt.sol +++ b/src/contracts/examples/oev-example/ChainlinkAtlasWrapperAlt.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; import { SafeERC20, IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/src/contracts/examples/oev-example/ChainlinkDAppControl.sol b/src/contracts/examples/oev-example/ChainlinkDAppControl.sol index ab190d88a..fc6d7ef2b 100644 --- a/src/contracts/examples/oev-example/ChainlinkDAppControl.sol +++ b/src/contracts/examples/oev-example/ChainlinkDAppControl.sol @@ -1,13 +1,13 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { ECDSA } from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { ChainlinkAtlasWrapper } from "src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { ChainlinkAtlasWrapper } from "./ChainlinkAtlasWrapper.sol"; // Role enum as per Chainlink's OffchainAggregatorBilling.sol contract enum Role { diff --git a/src/contracts/examples/oev-example/ChainlinkDAppControlAlt.sol b/src/contracts/examples/oev-example/ChainlinkDAppControlAlt.sol index d518c4eb4..53b699ad5 100644 --- a/src/contracts/examples/oev-example/ChainlinkDAppControlAlt.sol +++ b/src/contracts/examples/oev-example/ChainlinkDAppControlAlt.sol @@ -1,14 +1,14 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { ChainlinkAtlasWrapper } from "src/contracts/examples/oev-example/ChainlinkAtlasWrapperAlt.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { ChainlinkAtlasWrapper } from "./ChainlinkAtlasWrapperAlt.sol"; // Role enum as per Chainlink's OffchainAggregatorBilling.sol contract enum Role { diff --git a/src/contracts/examples/oev-example/IChainlinkAtlasWrapper.sol b/src/contracts/examples/oev-example/IChainlinkAtlasWrapper.sol index a45b6e7b8..01fa7d141 100644 --- a/src/contracts/examples/oev-example/IChainlinkAtlasWrapper.sol +++ b/src/contracts/examples/oev-example/IChainlinkAtlasWrapper.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { IChainlinkDAppControl } from "./IChainlinkDAppControl.sol"; diff --git a/src/contracts/examples/oev-example/IChainlinkDAppControl.sol b/src/contracts/examples/oev-example/IChainlinkDAppControl.sol index 3c0ff8944..663a77518 100644 --- a/src/contracts/examples/oev-example/IChainlinkDAppControl.sol +++ b/src/contracts/examples/oev-example/IChainlinkDAppControl.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; interface IChainlinkDAppControl { function verifyTransmitSigners( diff --git a/src/contracts/examples/trebleswap/TrebleSwapDAppControl.sol b/src/contracts/examples/trebleswap/TrebleSwapDAppControl.sol index c0d06f083..865b3c2ba 100644 --- a/src/contracts/examples/trebleswap/TrebleSwapDAppControl.sol +++ b/src/contracts/examples/trebleswap/TrebleSwapDAppControl.sol @@ -1,13 +1,13 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; struct SwapTokenInfo { address inputToken; diff --git a/src/contracts/examples/v2-example-router/V2RewardDAppControl.sol b/src/contracts/examples/v2-example-router/V2RewardDAppControl.sol index eae49ece4..667e27b65 100644 --- a/src/contracts/examples/v2-example-router/V2RewardDAppControl.sol +++ b/src/contracts/examples/v2-example-router/V2RewardDAppControl.sol @@ -1,15 +1,15 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; // Uniswap Imports import { IUniswapV2Router01, IUniswapV2Router02 } from "./interfaces/IUniswapV2Router.sol"; diff --git a/src/contracts/examples/v2-example/V2DAppControl.sol b/src/contracts/examples/v2-example/V2DAppControl.sol index 9eef3516a..591c68648 100644 --- a/src/contracts/examples/v2-example/V2DAppControl.sol +++ b/src/contracts/examples/v2-example/V2DAppControl.sol @@ -1,21 +1,21 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; // Atlas Base Imports -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; +import { IExecutionEnvironment } from "../../interfaces/IExecutionEnvironment.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; +import { SafetyBits } from "../../libraries/SafetyBits.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/UserOperation.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; // Uni V2 Imports import { IUniswapV2Pair } from "./interfaces/IUniswapV2Pair.sol"; diff --git a/src/contracts/examples/v4-example/IHooks.sol b/src/contracts/examples/v4-example/IHooks.sol index 3f4fa5caf..03d33c679 100644 --- a/src/contracts/examples/v4-example/IHooks.sol +++ b/src/contracts/examples/v4-example/IHooks.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { IPoolManager } from "./IPoolManager.sol"; diff --git a/src/contracts/examples/v4-example/IPoolManager.sol b/src/contracts/examples/v4-example/IPoolManager.sol index a2e49b34e..e9e022eba 100644 --- a/src/contracts/examples/v4-example/IPoolManager.sol +++ b/src/contracts/examples/v4-example/IPoolManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { IHooks } from "./IHooks.sol"; diff --git a/src/contracts/examples/v4-example/UniV4Hook.sol b/src/contracts/examples/v4-example/UniV4Hook.sol index 4ff2211aa..73da310d6 100644 --- a/src/contracts/examples/v4-example/UniV4Hook.sol +++ b/src/contracts/examples/v4-example/UniV4Hook.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // V4 Imports import { IPoolManager } from "./IPoolManager.sol"; @@ -8,14 +8,14 @@ import { IHooks } from "./IHooks.sol"; // Atlas Imports import { V4DAppControl } from "./V4DAppControl.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; +import { SafetyBits } from "../../libraries/SafetyBits.sol"; +import { SafeBlockNumber } from "../../libraries/SafeBlockNumber.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/LockTypes.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/UserOperation.sol"; +import "../../types/ConfigTypes.sol"; +import "../../types/LockTypes.sol"; // NOTE: Uniswap V4 is unique in that it would not require a frontend integration. // Instead, hooks can be used to enforce that the proceeds of the MEV auctions are diff --git a/src/contracts/examples/v4-example/V4DAppControl.sol b/src/contracts/examples/v4-example/V4DAppControl.sol index 75abab71f..3fb85aedd 100644 --- a/src/contracts/examples/v4-example/V4DAppControl.sol +++ b/src/contracts/examples/v4-example/V4DAppControl.sol @@ -1,23 +1,23 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Base Imports import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; // Atlas Base Imports -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; +import { IAtlas } from "../../interfaces/IAtlas.sol"; +import { SafetyBits } from "../../libraries/SafetyBits.sol"; +import { SafeBlockNumber } from "../../libraries/SafeBlockNumber.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/LockTypes.sol"; +import { CallConfig } from "../../types/ConfigTypes.sol"; +import "../../types/SolverOperation.sol"; +import "../../types/UserOperation.sol"; +import "../../types/ConfigTypes.sol"; +import "../../types/LockTypes.sol"; // Atlas DApp-Control Imports -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../dapp/DAppControl.sol"; // V4 Imports import { IPoolManager } from "./IPoolManager.sol"; diff --git a/src/contracts/gasCalculator/ArbitrumGasCalculator.sol b/src/contracts/gasCalculator/ArbitrumGasCalculator.sol index 7e202fc44..361a997b8 100644 --- a/src/contracts/gasCalculator/ArbitrumGasCalculator.sol +++ b/src/contracts/gasCalculator/ArbitrumGasCalculator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { ArbGasInfo } from "nitro-contracts/src/precompiles/ArbGasInfo.sol"; @@ -11,6 +11,7 @@ contract ArbitrumGasCalculator is IL2GasCalculator, Ownable { // Constants for gas calculations uint256 internal constant _CALLDATA_LENGTH_PREMIUM = 16; uint256 internal constant _BASE_TRANSACTION_GAS_USED = 21_000; + uint256 internal constant _ARBITRUM_NOVA_CHAINID = 42_170; // Interface to interact with Arbitrum's gas info precompile ArbGasInfo public immutable ARB_GAS_INFO; @@ -23,11 +24,10 @@ contract ArbitrumGasCalculator is IL2GasCalculator, Ownable { /// @notice Constructor /// @param calldataLenOffset Initial offset for calldata length calculations - /// @param _isArbitrumNova Flag to indicate if this is Arbitrum Nova - constructor(int256 calldataLenOffset, bool _isArbitrumNova) Ownable(msg.sender) { + constructor(int256 calldataLenOffset) Ownable(msg.sender) { ARB_GAS_INFO = ArbGasInfo(address(0x6c)); calldataLengthOffset = calldataLenOffset; - isArbitrumNova = _isArbitrumNova; + isArbitrumNova = block.chainid == _ARBITRUM_NOVA_CHAINID; } /// @notice Calculate the cost of calldata in ETH diff --git a/src/contracts/gasCalculator/BaseGasCalculator.sol b/src/contracts/gasCalculator/BaseGasCalculator.sol new file mode 100644 index 000000000..ff9b73208 --- /dev/null +++ b/src/contracts/gasCalculator/BaseGasCalculator.sol @@ -0,0 +1,66 @@ +//SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.28; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IL2GasCalculator } from "src/contracts/interfaces/IL2GasCalculator.sol"; + +/// @notice Implementation: +/// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/GasPriceOracle.sol +/// @notice Deployment on Base: https://basescan.org/address/0x420000000000000000000000000000000000000f +interface IGasPriceOracle { + function getL1FeeUpperBound(uint256 _unsignedTxSize) external view returns (uint256); +} + +contract BaseGasCalculator is IL2GasCalculator, Ownable { + uint256 internal constant _CALLDATA_LENGTH_PREMIUM = 16; + uint256 internal constant _BASE_TRANSACTION_GAS_USED = 21_000; + + address public immutable GAS_PRICE_ORACLE; + int256 public calldataLengthOffset; + + constructor(address gasPriceOracle, int256 calldataLenOffset) Ownable(msg.sender) { + GAS_PRICE_ORACLE = gasPriceOracle; + calldataLengthOffset = calldataLenOffset; + } + + /// @notice Calculate the cost of calldata in ETH on a L2 with a different fee structure than mainnet + /// @param calldataLength The length of the calldata in bytes + /// @return calldataCost The cost of the calldata in ETH + function getCalldataCost(uint256 calldataLength) external view override returns (uint256 calldataCost) { + // `getL1FeeUpperBound` returns the upper bound of the L1 fee in wei. It expects an unsigned transaction size in + // bytes, *not calldata length only*, which makes this function a rough estimate. + + // Base execution cost. + calldataCost = calldataLength * _CALLDATA_LENGTH_PREMIUM * tx.gasprice; + + // L1 data cost. + // `getL1FeeUpperBound` adds 68 to the size because it expects an unsigned transaction size. + // Remove 68 to the length to account for this. + if (calldataLength < 68) { + calldataLength = 0; + } else { + calldataLength -= 68; + } + + int256 _calldataLenOffset = calldataLengthOffset; + + if (_calldataLenOffset < 0 && calldataLength < uint256(-_calldataLenOffset)) { + return calldataCost; + } + + calldataLength += uint256(_calldataLenOffset); + calldataCost += IGasPriceOracle(GAS_PRICE_ORACLE).getL1FeeUpperBound(calldataLength); + } + + /// @notice Gets the cost of initial gas used for a transaction with a different calldata fee than mainnet + /// @param calldataLength The length of the calldata in bytes + function initialGasUsed(uint256 calldataLength) external pure override returns (uint256 gasUsed) { + return _BASE_TRANSACTION_GAS_USED + (calldataLength * _CALLDATA_LENGTH_PREMIUM); + } + + /// @notice Sets the calldata length offset + /// @param calldataLenOffset The new calldata length offset + function setCalldataLengthOffset(int256 calldataLenOffset) external onlyOwner { + calldataLengthOffset = calldataLenOffset; + } +} diff --git a/src/contracts/helpers/DemoLendingProtocol.sol b/src/contracts/helpers/DemoLendingProtocol.sol index ebe66343b..3a6ba24f3 100644 --- a/src/contracts/helpers/DemoLendingProtocol.sol +++ b/src/contracts/helpers/DemoLendingProtocol.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeERC20, IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; diff --git a/src/contracts/helpers/DemoToken.sol b/src/contracts/helpers/DemoToken.sol index c2e7a93d6..375783aa6 100644 --- a/src/contracts/helpers/DemoToken.sol +++ b/src/contracts/helpers/DemoToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; diff --git a/src/contracts/helpers/DemoWETH.sol b/src/contracts/helpers/DemoWETH.sol index 3824bd5ea..2b9c0f15d 100644 --- a/src/contracts/helpers/DemoWETH.sol +++ b/src/contracts/helpers/DemoWETH.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { WETH } from "solady/tokens/WETH.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; diff --git a/src/contracts/helpers/GovernanceBurner.sol b/src/contracts/helpers/GovernanceBurner.sol index e9914dd7d..325784c09 100644 --- a/src/contracts/helpers/GovernanceBurner.sol +++ b/src/contracts/helpers/GovernanceBurner.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; /// @title GovernanceBurner /// @author FastLane Labs diff --git a/src/contracts/helpers/Simulator.sol b/src/contracts/helpers/Simulator.sol index 34d9f3f33..5ac2653d7 100644 --- a/src/contracts/helpers/Simulator.sol +++ b/src/contracts/helpers/Simulator.sol @@ -1,21 +1,18 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; - -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; - -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/ValidCalls.sol"; -import "src/contracts/types/EscrowTypes.sol"; - -import { Result } from "src/contracts/interfaces/ISimulator.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/LockTypes.sol"; +import "../types/DAppOperation.sol"; +import "../types/ConfigTypes.sol"; +import "../types/ValidCalls.sol"; +import "../types/EscrowTypes.sol"; +import { AtlasErrors } from "../types/AtlasErrors.sol"; +import { Result } from "../interfaces/ISimulator.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; contract Simulator is AtlasErrors { address public immutable deployer; diff --git a/src/contracts/helpers/Sorter.sol b/src/contracts/helpers/Sorter.sol index aa3a9c2b5..448dfec78 100644 --- a/src/contracts/helpers/Sorter.sol +++ b/src/contracts/helpers/Sorter.sol @@ -1,19 +1,19 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; +import { IAtlasVerification } from "../interfaces/IAtlasVerification.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import { AccountingMath } from "src/contracts/libraries/AccountingMath.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; -import { AtlasConstants } from "src/contracts/types/AtlasConstants.sol"; +import { SafeBlockNumber } from "../libraries/SafeBlockNumber.sol"; +import { CallBits } from "../libraries/CallBits.sol"; +import { AccountingMath } from "../libraries/AccountingMath.sol"; +import { CallVerification } from "../libraries/CallVerification.sol"; +import { AtlasConstants } from "../types/AtlasConstants.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; contract Sorter is AtlasConstants { using CallBits for uint32; diff --git a/src/contracts/helpers/TxBuilder.sol b/src/contracts/helpers/TxBuilder.sol index 3e70fdc2e..2d95b81fb 100644 --- a/src/contracts/helpers/TxBuilder.sol +++ b/src/contracts/helpers/TxBuilder.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { IAtlasVerification } from "../interfaces/IAtlasVerification.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import "../types/DAppOperation.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; +import { CallVerification } from "../libraries/CallVerification.sol"; +import { CallBits } from "../libraries/CallBits.sol"; import "forge-std/Test.sol"; diff --git a/src/contracts/helpers/Utilities.sol b/src/contracts/helpers/Utilities.sol index a04978ff7..01cb6adca 100644 --- a/src/contracts/helpers/Utilities.sol +++ b/src/contracts/helpers/Utilities.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Script.sol"; import "forge-std/Test.sol"; diff --git a/src/contracts/interfaces/IAtlas.sol b/src/contracts/interfaces/IAtlas.sol index 65a9a3ce2..d66ce2adb 100644 --- a/src/contracts/interfaces/IAtlas.sol +++ b/src/contracts/interfaces/IAtlas.sol @@ -1,10 +1,10 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/LockTypes.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/DAppOperation.sol"; +import "../types/LockTypes.sol"; interface IAtlas { // Atlas.sol diff --git a/src/contracts/interfaces/IAtlasVerification.sol b/src/contracts/interfaces/IAtlasVerification.sol index cdd1eef7a..f8af0fa31 100644 --- a/src/contracts/interfaces/IAtlasVerification.sol +++ b/src/contracts/interfaces/IAtlasVerification.sol @@ -1,12 +1,12 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/ValidCalls.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import "../types/DAppOperation.sol"; +import "../types/SolverOperation.sol"; +import "../types/EscrowTypes.sol"; +import "../types/ValidCalls.sol"; interface IAtlasVerification { // AtlasVerification.sol diff --git a/src/contracts/interfaces/IDAppControl.sol b/src/contracts/interfaces/IDAppControl.sol index 25f699e85..20625d463 100644 --- a/src/contracts/interfaces/IDAppControl.sol +++ b/src/contracts/interfaces/IDAppControl.sol @@ -1,9 +1,9 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../types/UserOperation.sol"; +import "../types/SolverOperation.sol"; +import "../types/ConfigTypes.sol"; interface IDAppControl { function preOpsCall(UserOperation calldata userOp) external payable returns (bytes memory); diff --git a/src/contracts/interfaces/IExecutionEnvironment.sol b/src/contracts/interfaces/IExecutionEnvironment.sol index 17d7ecb55..af0c7e040 100644 --- a/src/contracts/interfaces/IExecutionEnvironment.sol +++ b/src/contracts/interfaces/IExecutionEnvironment.sol @@ -1,10 +1,10 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import "../types/EscrowTypes.sol"; interface IExecutionEnvironment { function preOpsWrapper(UserOperation calldata userOp) external returns (bytes memory preOpsData); diff --git a/src/contracts/interfaces/IL2GasCalculator.sol b/src/contracts/interfaces/IL2GasCalculator.sol index 33f7cc0be..41fd7c364 100644 --- a/src/contracts/interfaces/IL2GasCalculator.sol +++ b/src/contracts/interfaces/IL2GasCalculator.sol @@ -1,9 +1,9 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; interface IL2GasCalculator { /// @notice Calculate the cost of calldata in ETH on a L2 with a different fee structure than mainnet - function getCalldataCost(uint256 length) external view returns (uint256 calldataCostETH); + function getCalldataCost(uint256 calldataLength) external view returns (uint256 calldataCost); /// @notice Gets the cost of initial gas used for a transaction with a different calldata fee than mainnet function initialGasUsed(uint256 calldataLength) external view returns (uint256 gasUsed); } diff --git a/src/contracts/interfaces/ISimulator.sol b/src/contracts/interfaces/ISimulator.sol index 8a92a2ce1..ae2148744 100644 --- a/src/contracts/interfaces/ISimulator.sol +++ b/src/contracts/interfaces/ISimulator.sol @@ -1,10 +1,10 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; +import "../types/DAppOperation.sol"; enum Result { Unknown, diff --git a/src/contracts/interfaces/ISolverContract.sol b/src/contracts/interfaces/ISolverContract.sol index 047a3f779..e0a87a968 100644 --- a/src/contracts/interfaces/ISolverContract.sol +++ b/src/contracts/interfaces/ISolverContract.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/SolverOperation.sol"; +import "../types/SolverOperation.sol"; interface ISolverContract { function atlasSolverCall( diff --git a/src/contracts/libraries/AccountingMath.sol b/src/contracts/libraries/AccountingMath.sol index d30c044e1..43a941c47 100644 --- a/src/contracts/libraries/AccountingMath.sol +++ b/src/contracts/libraries/AccountingMath.sol @@ -1,29 +1,60 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; library AccountingMath { - // Gas Accounting public constants - uint256 internal constant _ATLAS_SURCHARGE_RATE = 1_000_000; // out of 10_000_000 = 10% - uint256 internal constant _BUNDLER_SURCHARGE_RATE = 1_000_000; // out of 10_000_000 = 10% + uint256 internal constant _MAX_BUNDLER_REFUND_RATE = 8_000_000; // out of 10_000_000 = 80% uint256 internal constant _SOLVER_GAS_LIMIT_BUFFER_PERCENTAGE = 500_000; // out of 10_000_000 = 5% uint256 internal constant _SCALE = 10_000_000; // 10_000_000 / 10_000_000 = 100% uint256 internal constant _FIXED_GAS_OFFSET = 85_000; - function withBundlerSurcharge(uint256 amount) internal pure returns (uint256 adjustedAmount) { - adjustedAmount = amount * (_SCALE + _BUNDLER_SURCHARGE_RATE) / _SCALE; + function withSurcharge(uint256 amount, uint256 surchargeRate) internal pure returns (uint256 adjustedAmount) { + adjustedAmount = amount * (_SCALE + surchargeRate) / _SCALE; } - function withoutBundlerSurcharge(uint256 amount) internal pure returns (uint256 unadjustedAmount) { - unadjustedAmount = amount * _SCALE / (_SCALE + _BUNDLER_SURCHARGE_RATE); + function withoutSurcharge(uint256 amount, uint256 surchargeRate) internal pure returns (uint256 unadjustedAmount) { + unadjustedAmount = amount * _SCALE / (_SCALE + surchargeRate); } - function withAtlasAndBundlerSurcharges(uint256 amount) internal pure returns (uint256 adjustedAmount) { - adjustedAmount = amount * (_SCALE + _ATLAS_SURCHARGE_RATE + _BUNDLER_SURCHARGE_RATE) / _SCALE; + function withSurcharges( + uint256 amount, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate + ) + internal + pure + returns (uint256 adjustedAmount) + { + adjustedAmount = amount * (_SCALE + atlasSurchargeRate + bundlerSurchargeRate) / _SCALE; } // gets the Atlas surcharge from an unadjusted amount - function getAtlasSurcharge(uint256 amount) internal pure returns (uint256 surcharge) { - surcharge = amount * _ATLAS_SURCHARGE_RATE / _SCALE; + function getSurcharge( + uint256 unadjustedAmount, + uint256 surchargeRate + ) + internal + pure + returns (uint256 surchargeAmount) + { + surchargeAmount = unadjustedAmount * surchargeRate / _SCALE; + } + + function getPortionFromTotalSurcharge( + uint256 totalSurcharge, + uint256 targetSurchargeRate, + uint256 totalSurchargeRate + ) + internal + pure + returns (uint256 surchargePortion) + { + surchargePortion = totalSurcharge * targetSurchargeRate / totalSurchargeRate; + } + + // NOTE: This max should only be applied when there are no winning solvers. + // Set to 80% of the metacall gas cost, because the remaining 20% can be collected through storage refunds. + function maxBundlerRefund(uint256 metacallGasCost) internal pure returns (uint256 maxRefund) { + maxRefund = metacallGasCost * _MAX_BUNDLER_REFUND_RATE / _SCALE; } function solverGasLimitScaledDown( diff --git a/src/contracts/libraries/CallBits.sol b/src/contracts/libraries/CallBits.sol index 62b46a465..53abaa446 100644 --- a/src/contracts/libraries/CallBits.sol +++ b/src/contracts/libraries/CallBits.sol @@ -1,9 +1,9 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; +import { IDAppControl } from "../interfaces/IDAppControl.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../types/ConfigTypes.sol"; library CallBits { uint32 internal constant _ONE = uint32(1); diff --git a/src/contracts/libraries/CallVerification.sol b/src/contracts/libraries/CallVerification.sol index 6c41ee411..4eab4c580 100644 --- a/src/contracts/libraries/CallVerification.sol +++ b/src/contracts/libraries/CallVerification.sol @@ -1,11 +1,11 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../types/SolverOperation.sol"; +import "../types/UserOperation.sol"; +import "../types/ConfigTypes.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; +import { CallBits } from "./CallBits.sol"; library CallVerification { using CallBits for uint32; diff --git a/src/contracts/libraries/EscrowBits.sol b/src/contracts/libraries/EscrowBits.sol index 392f7bb7b..aa5eb28f6 100644 --- a/src/contracts/libraries/EscrowBits.sol +++ b/src/contracts/libraries/EscrowBits.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/EscrowTypes.sol"; +import "../types/EscrowTypes.sol"; library EscrowBits { // Bundler's Fault - solver doesn't owe any gas refund. SolverOp isn't executed diff --git a/src/contracts/libraries/SafeCall/SafeCall.sol b/src/contracts/libraries/SafeCall/SafeCall.sol index db83111d1..02ca156fc 100644 --- a/src/contracts/libraries/SafeCall/SafeCall.sol +++ b/src/contracts/libraries/SafeCall/SafeCall.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; /// @title SafeCall /// @author FastLane Labs diff --git a/src/contracts/libraries/SafetyBits.sol b/src/contracts/libraries/SafetyBits.sol index ab8231701..e912807e9 100644 --- a/src/contracts/libraries/SafetyBits.sol +++ b/src/contracts/libraries/SafetyBits.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/LockTypes.sol"; +import "../types/LockTypes.sol"; // NOTE: No user transfers allowed during AllocateValue uint8 constant SAFE_USER_TRANSFER = uint8( diff --git a/src/contracts/solver/SolverBase.sol b/src/contracts/solver/SolverBase.sol index 88cccac67..ea9553bc1 100644 --- a/src/contracts/solver/SolverBase.sol +++ b/src/contracts/solver/SolverBase.sol @@ -1,13 +1,13 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ISolverContract } from "src/contracts/interfaces/ISolverContract.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { ISolverContract } from "../interfaces/ISolverContract.sol"; -import "src/contracts/types/SolverOperation.sol"; +import "../types/SolverOperation.sol"; interface IWETH9 { function deposit() external payable; @@ -42,7 +42,7 @@ contract SolverBase is ISolverContract { address bidToken, uint256 bidAmount, bytes calldata solverOpData, - bytes calldata + bytes calldata forwardedData ) external payable diff --git a/src/contracts/solver/SolverBaseInvertBid.sol b/src/contracts/solver/SolverBaseInvertBid.sol index 3924665e0..8963df9f7 100644 --- a/src/contracts/solver/SolverBaseInvertBid.sol +++ b/src/contracts/solver/SolverBaseInvertBid.sol @@ -1,13 +1,13 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { ISolverContract } from "src/contracts/interfaces/ISolverContract.sol"; +import { IAtlas } from "../interfaces/IAtlas.sol"; +import { ISolverContract } from "../interfaces/ISolverContract.sol"; -import "src/contracts/types/SolverOperation.sol"; +import "../types/SolverOperation.sol"; interface IWETH9 { function deposit() external payable; diff --git a/src/contracts/solver/src/TestSolver.sol b/src/contracts/solver/src/TestSolver.sol index 0e9a22475..5f5441a5a 100644 --- a/src/contracts/solver/src/TestSolver.sol +++ b/src/contracts/solver/src/TestSolver.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { SolverBase } from "../../solver/SolverBase.sol"; // Flashbots opensource repo import { BlindBackrun } from "./BlindBackrun/BlindBackrun.sol"; diff --git a/src/contracts/solver/src/TestSolverExPost.sol b/src/contracts/solver/src/TestSolverExPost.sol index 2bf3cd0eb..74dbbbe9e 100644 --- a/src/contracts/solver/src/TestSolverExPost.sol +++ b/src/contracts/solver/src/TestSolverExPost.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { SolverBase } from "../../solver/SolverBase.sol"; // Flashbots opensource repo import { BlindBackrun } from "./BlindBackrun/BlindBackrun.sol"; diff --git a/src/contracts/types/AtlasConstants.sol b/src/contracts/types/AtlasConstants.sol index da2b78397..89e4f5e23 100644 --- a/src/contracts/types/AtlasConstants.sol +++ b/src/contracts/types/AtlasConstants.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/ValidCalls.sol"; +import "./ValidCalls.sol"; // NOTE: Internal constants that are defined but not used in the logic of a smart contract, will NOT be included in the // bytecode of the smart contract when compiled. However, public constants will be included in every inheriting contract @@ -18,10 +18,12 @@ contract AtlasConstants { // Atlas constants used in `_bidFindingIteration()` uint256 internal constant _BITS_FOR_INDEX = 16; + uint256 internal constant _FIRST_16_BITS_TRUE_MASK = uint256(0xFFFF); // Escrow constants uint256 internal constant _VALIDATION_GAS_LIMIT = 500_000; uint256 internal constant _FASTLANE_GAS_BUFFER = 125_000; // integer amount + uint256 internal constant _GRACEFUL_RETURN_GAS_OFFSET = 40_000; // Gas Accounting constants uint256 internal constant _CALLDATA_LENGTH_PREMIUM = 32; // 16 (default) * 2 @@ -37,7 +39,8 @@ contract AtlasConstants { uint256 internal constant _SOLVER_FULFILLED_MASK = 1 << 162; // Used to set Lock phase without changing the activeEnvironment or callConfig. - bytes32 internal constant _LOCK_PHASE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00; + uint256 internal constant _LOCK_PHASE_MASK = + uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00); // ValidCalls error threshold before which the metacall reverts, and after which it returns gracefully to store // nonces as used. @@ -47,16 +50,5 @@ contract AtlasConstants { // ATLAS VERIFICATION CONSTANTS // // ------------------------------------------------------- // - uint256 internal constant _FULL_BITMAP = _FIRST_240_BITS_TRUE_MASK; - uint256 internal constant _NONCES_PER_BITMAP = 240; uint8 internal constant _MAX_SOLVERS = type(uint8).max - 1; - - // ------------------------------------------------------- // - // SHARED CONSTANTS // - // ------------------------------------------------------- // - - uint256 internal constant _FIRST_240_BITS_TRUE_MASK = - uint256(0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - uint256 internal constant _FIRST_16_BITS_TRUE_MASK = uint256(0xFFFF); - uint256 internal constant _FIRST_4_BITS_TRUE_MASK = uint256(0xF); } diff --git a/src/contracts/types/AtlasErrors.sol b/src/contracts/types/AtlasErrors.sol index 163a22afe..606f7239f 100644 --- a/src/contracts/types/AtlasErrors.sol +++ b/src/contracts/types/AtlasErrors.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/types/ValidCalls.sol"; +import "./ValidCalls.sol"; contract AtlasErrors { // Simulator diff --git a/src/contracts/types/AtlasEvents.sol b/src/contracts/types/AtlasEvents.sol index d53e93e9b..54093db8e 100644 --- a/src/contracts/types/AtlasEvents.sol +++ b/src/contracts/types/AtlasEvents.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; contract AtlasEvents { // Metacall @@ -21,7 +21,14 @@ contract AtlasEvents { // Escrow events event SolverTxResult( - address indexed solverTo, address indexed solverFrom, bool executed, bool success, uint256 result + address indexed solverTo, + address indexed solverFrom, + address indexed dAppControl, + address bidToken, + uint256 bidAmount, + bool executed, + bool success, + uint256 result ); // Factory events diff --git a/src/contracts/types/ConfigTypes.sol b/src/contracts/types/ConfigTypes.sol index 39605bce9..f68e327b5 100644 --- a/src/contracts/types/ConfigTypes.sol +++ b/src/contracts/types/ConfigTypes.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; struct DAppConfig { address to; // Address of the DAppControl contract diff --git a/src/contracts/types/DAppOperation.sol b/src/contracts/types/DAppOperation.sol index 897563d16..82a3b1d1c 100644 --- a/src/contracts/types/DAppOperation.sol +++ b/src/contracts/types/DAppOperation.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; bytes32 constant DAPP_TYPEHASH = keccak256( "DAppOperation(address from,address to,uint256 nonce,uint256 deadline,address control,address bundler,bytes32 userOpHash,bytes32 callChainHash)" diff --git a/src/contracts/types/EscrowTypes.sol b/src/contracts/types/EscrowTypes.sol index 7568cb582..c5e8f393c 100644 --- a/src/contracts/types/EscrowTypes.sol +++ b/src/contracts/types/EscrowTypes.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // bonded = total - unbonding struct EscrowAccountBalance { diff --git a/src/contracts/types/LockTypes.sol b/src/contracts/types/LockTypes.sol index f5831ff6d..938b7199b 100644 --- a/src/contracts/types/LockTypes.sol +++ b/src/contracts/types/LockTypes.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; struct Context { bytes32 userOpHash; // not packed diff --git a/src/contracts/types/SolverOperation.sol b/src/contracts/types/SolverOperation.sol index 7e6bf94bf..d58c73952 100644 --- a/src/contracts/types/SolverOperation.sol +++ b/src/contracts/types/SolverOperation.sol @@ -1,13 +1,13 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; bytes32 constant SOLVER_TYPEHASH = keccak256( "SolverOperation(address from,address to,uint256 value,uint256 gas,uint256 maxFeePerGas,uint256 deadline,address solver,address control,bytes32 userOpHash,address bidToken,uint256 bidAmount,bytes data)" ); // NOTE: The calldata length of this SolverOperation struct is 608 bytes when the `data` field is excluded. This value -// is stored in the `_SOLVER_OP_BASE_CALLDATA` constant in Storage.sol and must be kept up-to-date with any changes to -// this struct. +// is stored in the `_SOLVER_OP_BASE_CALLDATA` constant in AtlasConstants.sol and must be kept up-to-date with any +// changes to this struct. struct SolverOperation { address from; // Solver address address to; // Atlas address diff --git a/src/contracts/types/UserOperation.sol b/src/contracts/types/UserOperation.sol index de80f5c20..3a6d06600 100644 --- a/src/contracts/types/UserOperation.sol +++ b/src/contracts/types/UserOperation.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; // Default UserOperation typehash bytes32 constant USER_TYPEHASH_DEFAULT = keccak256( diff --git a/src/contracts/types/ValidCalls.sol b/src/contracts/types/ValidCalls.sol index 43a996434..0831a98a2 100644 --- a/src/contracts/types/ValidCalls.sol +++ b/src/contracts/types/ValidCalls.sol @@ -1,5 +1,5 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; /// @title ValidCallsResult /// @notice Enum for ValidCallsResult diff --git a/test/Accounting.t.sol b/test/Accounting.t.sol index 446f78a2e..79853bbe4 100644 --- a/test/Accounting.t.sol +++ b/test/Accounting.t.sol @@ -1,20 +1,20 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { DAppConfig } from "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import "src/contracts/types/LockTypes.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; +import { SafetyBits } from "../src/contracts/libraries/SafetyBits.sol"; +import "../src/contracts/types/LockTypes.sol"; import { TestUtils } from "./base/TestUtils.sol"; @@ -22,9 +22,9 @@ import { SwapIntentDAppControl, SwapIntent, Condition -} from "src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; +} from "../src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; contract AccountingTest is BaseTest { SwapIntentDAppControl public swapIntentControl; diff --git a/test/AccountingMath.t.sol b/test/AccountingMath.t.sol index a9b26d180..1a380ca6c 100644 --- a/test/AccountingMath.t.sol +++ b/test/AccountingMath.t.sol @@ -1,72 +1,87 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import "src/contracts/libraries/AccountingMath.sol"; +import "../src/contracts/libraries/AccountingMath.sol"; contract AccountingMathTest is Test { + uint256 DEFAULT_ATLAS_SURCHARGE_RATE = 1_000_000; // 10% + uint256 DEFAULT_BUNDLER_SURCHARGE_RATE = 1_000_000; // 10% + function testWithBundlerSurcharge() public { - assertEq(AccountingMath.withBundlerSurcharge(0), uint256(0)); - assertEq(AccountingMath.withBundlerSurcharge(1), uint256(1)); - assertEq(AccountingMath.withBundlerSurcharge(11), uint256(12)); - assertEq(AccountingMath.withBundlerSurcharge(100), uint256(110)); - assertEq(AccountingMath.withBundlerSurcharge(1e18), uint256(11e17)); + assertEq(AccountingMath.withSurcharge(0, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(0)); + assertEq(AccountingMath.withSurcharge(1, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(1)); + assertEq(AccountingMath.withSurcharge(11, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(12)); + assertEq(AccountingMath.withSurcharge(100, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(110)); + assertEq(AccountingMath.withSurcharge(1e18, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(11e17)); vm.expectRevert(); - AccountingMath.withBundlerSurcharge(type(uint256).max); + AccountingMath.withSurcharge(type(uint256).max, DEFAULT_BUNDLER_SURCHARGE_RATE); } function testWithoutBundlerSurcharge() public { - assertEq(AccountingMath.withoutBundlerSurcharge(0), uint256(0)); - assertEq(AccountingMath.withoutBundlerSurcharge(1), uint256(0)); - assertEq(AccountingMath.withoutBundlerSurcharge(12), uint256(10)); - assertEq(AccountingMath.withoutBundlerSurcharge(110), uint256(100)); - assertEq(AccountingMath.withoutBundlerSurcharge(11e17), uint256(1e18)); + assertEq(AccountingMath.withoutSurcharge(0, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(0)); + assertEq(AccountingMath.withoutSurcharge(1, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(0)); + assertEq(AccountingMath.withoutSurcharge(12, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(10)); + assertEq(AccountingMath.withoutSurcharge(110, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(100)); + assertEq(AccountingMath.withoutSurcharge(11e17, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(1e18)); vm.expectRevert(); - AccountingMath.withoutBundlerSurcharge(type(uint256).max); + AccountingMath.withoutSurcharge(type(uint256).max, DEFAULT_BUNDLER_SURCHARGE_RATE); } function testWithAtlasAndBundlerSurcharges() public { - assertEq(AccountingMath.withAtlasAndBundlerSurcharges(0), uint256(0)); - assertEq(AccountingMath.withAtlasAndBundlerSurcharges(1), uint256(1)); - assertEq(AccountingMath.withAtlasAndBundlerSurcharges(10), uint256(12)); - assertEq(AccountingMath.withAtlasAndBundlerSurcharges(100), uint256(120)); - assertEq(AccountingMath.withAtlasAndBundlerSurcharges(1e18), uint256(12e17)); + assertEq( + AccountingMath.withSurcharges(0, DEFAULT_ATLAS_SURCHARGE_RATE, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(0) + ); + assertEq( + AccountingMath.withSurcharges(1, DEFAULT_ATLAS_SURCHARGE_RATE, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(1) + ); + assertEq( + AccountingMath.withSurcharges(10, DEFAULT_ATLAS_SURCHARGE_RATE, DEFAULT_BUNDLER_SURCHARGE_RATE), uint256(12) + ); + assertEq( + AccountingMath.withSurcharges(100, DEFAULT_ATLAS_SURCHARGE_RATE, DEFAULT_BUNDLER_SURCHARGE_RATE), + uint256(120) + ); + assertEq( + AccountingMath.withSurcharges(1e18, DEFAULT_ATLAS_SURCHARGE_RATE, DEFAULT_BUNDLER_SURCHARGE_RATE), + uint256(12e17) + ); vm.expectRevert(); - AccountingMath.withAtlasAndBundlerSurcharges(type(uint256).max); + AccountingMath.withSurcharges(type(uint256).max, DEFAULT_ATLAS_SURCHARGE_RATE, DEFAULT_BUNDLER_SURCHARGE_RATE); } function testGetAtlasSurcharge() public { - assertEq(AccountingMath.getAtlasSurcharge(0), uint256(0)); - assertEq(AccountingMath.getAtlasSurcharge(10), uint256(1)); - assertEq(AccountingMath.getAtlasSurcharge(20), uint256(2)); - assertEq(AccountingMath.getAtlasSurcharge(30), uint256(3)); - assertEq(AccountingMath.getAtlasSurcharge(100), uint256(10)); - assertEq(AccountingMath.getAtlasSurcharge(1_000_000), uint256(100_000)); - assertEq(AccountingMath.getAtlasSurcharge(1e18), uint256(1e17)); + assertEq(AccountingMath.getSurcharge(0, DEFAULT_ATLAS_SURCHARGE_RATE), uint256(0)); + assertEq(AccountingMath.getSurcharge(10, DEFAULT_ATLAS_SURCHARGE_RATE), uint256(1)); + assertEq(AccountingMath.getSurcharge(20, DEFAULT_ATLAS_SURCHARGE_RATE), uint256(2)); + assertEq(AccountingMath.getSurcharge(30, DEFAULT_ATLAS_SURCHARGE_RATE), uint256(3)); + assertEq(AccountingMath.getSurcharge(100, DEFAULT_ATLAS_SURCHARGE_RATE), uint256(10)); + assertEq(AccountingMath.getSurcharge(1_000_000, DEFAULT_ATLAS_SURCHARGE_RATE), uint256(100_000)); + assertEq(AccountingMath.getSurcharge(1e18, DEFAULT_ATLAS_SURCHARGE_RATE), uint256(1e17)); vm.expectRevert(); - AccountingMath.getAtlasSurcharge(type(uint256).max); + AccountingMath.getSurcharge(type(uint256).max, DEFAULT_ATLAS_SURCHARGE_RATE); } function testSolverGasLimitScaledDown() public { assertEq(AccountingMath.solverGasLimitScaledDown(0, 100), uint256(0)); assertEq(AccountingMath.solverGasLimitScaledDown(50, 100), uint256(47)); // 50 * 10_000_000 / 10_500_000 assertEq(AccountingMath.solverGasLimitScaledDown(100, 200), uint256(95)); - + assertEq(AccountingMath.solverGasLimitScaledDown(200, 100), uint256(95)); assertEq(AccountingMath.solverGasLimitScaledDown(300, 200), uint256(190)); - + assertEq(AccountingMath.solverGasLimitScaledDown(100, 100), uint256(95)); assertEq(AccountingMath.solverGasLimitScaledDown(200, 200), uint256(190)); - - assertEq(AccountingMath.solverGasLimitScaledDown(1_000_000, 500_000), uint256(476_190)); // 500_000 * 10_000_000 / 10_500_000 - assertEq(AccountingMath.solverGasLimitScaledDown(1e18, 1e18), uint256(952380952380952380)); - + + assertEq(AccountingMath.solverGasLimitScaledDown(1_000_000, 500_000), uint256(476_190)); // 500_000 * 10_000_000 + // / 10_500_000 + assertEq(AccountingMath.solverGasLimitScaledDown(1e18, 1e18), uint256(952_380_952_380_952_380)); + vm.expectRevert(); assertEq(AccountingMath.solverGasLimitScaledDown(type(uint256).max, type(uint256).max), type(uint256).max); - + assertEq(AccountingMath.solverGasLimitScaledDown(1, 2), uint256(0)); // 1 * 10_000_000 / 10_500_000 assertEq(AccountingMath.solverGasLimitScaledDown(3, 3), uint256(2)); // 3 * 10_000_000 / 10_500_000 assertEq(AccountingMath.solverGasLimitScaledDown(5, 10), uint256(4)); // 5 * 10_000_000 / 10_500_000 - } } diff --git a/test/AtlETH.t.sol b/test/AtlETH.t.sol index 395617517..8680aa533 100644 --- a/test/AtlETH.t.sol +++ b/test/AtlETH.t.sol @@ -1,12 +1,13 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import {AtlasEvents} from "src/contracts/types/AtlasEvents.sol"; -import {AtlasErrors} from "src/contracts/types/AtlasErrors.sol"; + +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; contract AtlETHTest is BaseTest { diff --git a/test/Atlas.t.sol b/test/Atlas.t.sol deleted file mode 100644 index f64d010cf..000000000 --- a/test/Atlas.t.sol +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.25; - -import "forge-std/Test.sol"; - -import { BaseTest } from "test/base/BaseTest.t.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { UserOperationBuilder } from "test/base/builders/UserOperationBuilder.sol"; - -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; -import { Sorter } from "src/contracts/helpers/Sorter.sol"; -import { Simulator } from "src/contracts/helpers/Simulator.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/LockTypes.sol"; - -import { LibSort } from "solady/utils/LibSort.sol"; - -// These tests focus on the functions found in the Atlas.sol file -contract AtlasTest is BaseTest { - - function setUp_bidFindingIteration() public { - // super.setUp(); - - // vm.startPrank(payee); - // simulator = new Simulator(); - - // // Computes the addresses at which AtlasVerification will be deployed - // address expectedAtlasAddr = vm.computeCreateAddress(payee, vm.getNonce(payee) + 1); - // address expectedAtlasVerificationAddr = vm.computeCreateAddress(payee, vm.getNonce(payee) + 2); - // bytes32 salt = keccak256(abi.encodePacked(block.chainid, expectedAtlasAddr, "AtlasFactory 1.0")); - // ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment{ salt: salt }(expectedAtlasAddr); - - // atlas = new MockAtlas({ - // escrowDuration: 64, - // verification: expectedAtlasVerificationAddr, - // simulator: address(simulator), - // executionTemplate: address(execEnvTemplate), - // surchargeRecipient: payee - // }); - // atlasVerification = new AtlasVerification(address(atlas)); - // simulator.setAtlas(address(atlas)); - // sorter = new Sorter(address(atlas)); - // vm.stopPrank(); - } - - function test_bidFindingIteration_sortingOrder() public pure { - // Test order of bidsAndIndices after insertionSort - - // 3 items. [200, 0, 100] --> [0, 100, 200] - uint256[] memory bidsAndIndices = new uint256[](3); - bidsAndIndices[0] = 100; - bidsAndIndices[1] = 0; - bidsAndIndices[2] = 300; - - LibSort.insertionSort(bidsAndIndices); - assertEq(bidsAndIndices[0], 0); - assertEq(bidsAndIndices[1], 100); - assertEq(bidsAndIndices[2], 300); - - // 1 item. [100] --> [100] - bidsAndIndices = new uint256[](1); - bidsAndIndices[0] = 100; - - LibSort.insertionSort(bidsAndIndices); - assertEq(bidsAndIndices[0], 100); - - // 2 items. [100, 0] --> [0, 100] - bidsAndIndices = new uint256[](2); - bidsAndIndices[0] = 100; - bidsAndIndices[1] = 0; - - LibSort.insertionSort(bidsAndIndices); - assertEq(bidsAndIndices[0], 0); - assertEq(bidsAndIndices[1], 100); - } - - function test_bidFindingIteration_packBidAndIndex() public pure { - uint256 bid = 12345; - uint256 index = 2; - - uint256 packed = _packBidAndIndex(bid, index); - (uint256 unpackedBid, uint256 unpackedIndex) = _unpackBidAndIndex(packed); - assertEq(unpackedBid, bid); - assertEq(unpackedIndex, index); - - bid = type(uint240).max - 1; - index = 7; - - packed = _packBidAndIndex(bid, index); - (unpackedBid, unpackedIndex) = _unpackBidAndIndex(packed); - assertEq(unpackedBid, bid); - assertEq(unpackedIndex, index); - - bid = 0; - index = 1; - - packed = _packBidAndIndex(bid, index); - (unpackedBid, unpackedIndex) = _unpackBidAndIndex(packed); - assertEq(unpackedBid, bid); - assertEq(unpackedIndex, index); - - bid = 1; - index = 0; - - packed = _packBidAndIndex(bid, index); - (unpackedBid, unpackedIndex) = _unpackBidAndIndex(packed); - assertEq(unpackedBid, bid); - assertEq(unpackedIndex, index); - } - - - // Packs bid and index into a single uint256, replicates logic used in `_bidFindingIteration()` - function _packBidAndIndex(uint256 bid, uint256 index) internal pure returns (uint256) { - return uint256(bid << 16 | uint16(index)); - } - - // Unpacks bid and index from a single uint256, replicates logic used in `_bidFindingIteration()` - function _unpackBidAndIndex(uint256 packed) internal pure returns (uint256 bid, uint256 index) { - // bidAmountFound = (bidsAndIndices[i] >> BITS_FOR_INDEX) & FIRST_240_BITS_MASK; - bid = (packed >> 16) & uint256(0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - // uint256 solverOpsIndex = bidsAndIndices[i] & FIRST_16_BITS_MASK; - index = packed & uint256(0xFFFF); - } -} - -// MockAtlas exposes Atlas' internal functions for testing -contract MockAtlas is Atlas { - constructor( - uint256 _escrowDuration, - address _verification, - address _simulator, - address _surchargeRecipient, - address _l2GasCalculator, - address _executionTemplate - ) - Atlas(_escrowDuration, _verification, _simulator, _surchargeRecipient, _l2GasCalculator, _executionTemplate) - { } - - function bidFindingIteration( - DAppConfig calldata dConfig, - UserOperation calldata userOp, - SolverOperation[] calldata solverOps, - bytes memory returnData, - Context memory ctx - ) public returns (Context memory) { - _bidFindingIteration(ctx, dConfig, userOp, solverOps, returnData); - return ctx; - } -} \ No newline at end of file diff --git a/test/AtlasVerification.t.sol b/test/AtlasVerification.t.sol index 3712bc696..d46868554 100644 --- a/test/AtlasVerification.t.sol +++ b/test/AtlasVerification.t.sol @@ -1,21 +1,21 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { AtlasVerification, USER_TYPEHASH_DEFAULT, USER_TYPEHASH_TRUSTED } from "src/contracts/atlas/AtlasVerification.sol"; -import { DAppConfig, CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { ValidCallsResult } from "src/contracts/types/ValidCalls.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import { AtlasVerification, USER_TYPEHASH_DEFAULT, USER_TYPEHASH_TRUSTED } from "../src/contracts/atlas/AtlasVerification.sol"; +import { DAppConfig, CallConfig } from "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { ValidCallsResult } from "../src/contracts/types/ValidCalls.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; import { DummyDAppControl } from "./base/DummyDAppControl.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import { SolverOutcome } from "src/contracts/types/EscrowTypes.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; +import { CallVerification } from "../src/contracts/libraries/CallVerification.sol"; +import { CallBits } from "../src/contracts/libraries/CallBits.sol"; +import { SolverOutcome } from "../src/contracts/types/EscrowTypes.sol"; import { DummyDAppControlBuilder } from "./helpers/DummyDAppControlBuilder.sol"; import { CallConfigBuilder } from "./helpers/CallConfigBuilder.sol"; import { UserOperationBuilder } from "./base/builders/UserOperationBuilder.sol"; diff --git a/test/BidFinding.t.sol b/test/BidFinding.t.sol new file mode 100644 index 000000000..c31e30bc7 --- /dev/null +++ b/test/BidFinding.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/Test.sol"; +import { LibSort } from "solady/utils/LibSort.sol"; +import { BaseTest } from "./base/BaseTest.t.sol"; + +contract BidFindingTest is BaseTest { + function test_bidFindingIteration_sortingOrder() public pure { + // Test order of bidsAndIndices after insertionSort + + // 3 items. [200, 0, 100] --> [0, 100, 200] + uint256[] memory bidsAndIndices = new uint256[](3); + bidsAndIndices[0] = 100; + bidsAndIndices[1] = 0; + bidsAndIndices[2] = 300; + + LibSort.insertionSort(bidsAndIndices); + assertEq(bidsAndIndices[0], 0); + assertEq(bidsAndIndices[1], 100); + assertEq(bidsAndIndices[2], 300); + + // 1 item. [100] --> [100] + bidsAndIndices = new uint256[](1); + bidsAndIndices[0] = 100; + + LibSort.insertionSort(bidsAndIndices); + assertEq(bidsAndIndices[0], 100); + + // 2 items. [100, 0] --> [0, 100] + bidsAndIndices = new uint256[](2); + bidsAndIndices[0] = 100; + bidsAndIndices[1] = 0; + + LibSort.insertionSort(bidsAndIndices); + assertEq(bidsAndIndices[0], 0); + assertEq(bidsAndIndices[1], 100); + } + + function test_bidFindingIteration_packBidAndIndex() public pure { + uint256 bid = 12_345; + uint256 index = 2; + + uint256 packed = _packBidAndIndex(bid, index); + (uint256 unpackedBid, uint256 unpackedIndex) = _unpackBidAndIndex(packed); + assertEq(unpackedBid, bid); + assertEq(unpackedIndex, index); + + bid = type(uint240).max - 1; + index = 7; + + packed = _packBidAndIndex(bid, index); + (unpackedBid, unpackedIndex) = _unpackBidAndIndex(packed); + assertEq(unpackedBid, bid); + assertEq(unpackedIndex, index); + + bid = 0; + index = 1; + + packed = _packBidAndIndex(bid, index); + (unpackedBid, unpackedIndex) = _unpackBidAndIndex(packed); + assertEq(unpackedBid, bid); + assertEq(unpackedIndex, index); + + bid = 1; + index = 0; + + packed = _packBidAndIndex(bid, index); + (unpackedBid, unpackedIndex) = _unpackBidAndIndex(packed); + assertEq(unpackedBid, bid); + assertEq(unpackedIndex, index); + } + + // Packs bid and index into a single uint256, replicates logic used in `_bidFindingIteration()` + function _packBidAndIndex(uint256 bid, uint256 index) internal pure returns (uint256) { + return uint256(bid << 16 | uint16(index)); + } + + // Unpacks bid and index from a single uint256, replicates logic used in `_bidFindingIteration()` + function _unpackBidAndIndex(uint256 packed) internal pure returns (uint256 bid, uint256 index) { + // bidAmountFound = (bidsAndIndices[i] >> BITS_FOR_INDEX) & FIRST_240_BITS_MASK; + bid = (packed >> 16) & uint256(0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + // uint256 solverOpsIndex = bidsAndIndices[i] & FIRST_16_BITS_MASK; + index = packed & uint256(0xFFFF); + } +} diff --git a/test/DAppIntegration.t.sol b/test/DAppIntegration.t.sol index 7bbb5c08e..e714d2c93 100644 --- a/test/DAppIntegration.t.sol +++ b/test/DAppIntegration.t.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; -import { DAppIntegration } from "src/contracts/atlas/DAppIntegration.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; +import { FactoryLib } from "../src/contracts/atlas/FactoryLib.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { ExecutionEnvironment } from "../src/contracts/common/ExecutionEnvironment.sol"; +import { DAppIntegration } from "../src/contracts/atlas/DAppIntegration.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; import { DummyDAppControl, CallConfigBuilder } from "./base/DummyDAppControl.sol"; @@ -16,10 +17,14 @@ contract MockDAppIntegration is DAppIntegration { } contract DAppIntegrationTest is Test { + uint256 DEFAULT_ATLAS_SURCHARGE_RATE = 1_000_000; // 10% + uint256 DEFAULT_BUNDLER_SURCHARGE_RATE = 1_000_000; // 10% + Atlas public atlas; MockDAppIntegration public dAppIntegration; DummyDAppControl public dAppControl; AtlasVerification atlasVerification; + FactoryLib factoryLib; address atlasDeployer = makeAddr("atlas deployer"); address governance = makeAddr("governance"); @@ -30,19 +35,22 @@ contract DAppIntegrationTest is Test { vm.startPrank(atlasDeployer); // Compute expected addresses for Atlas - address expectedAtlasAddr = vm.computeCreateAddress(atlasDeployer, vm.getNonce(atlasDeployer) + 2); + address expectedAtlasAddr = vm.computeCreateAddress(atlasDeployer, vm.getNonce(atlasDeployer) + 3); ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment(expectedAtlasAddr); // Deploy the AtlasVerification contract atlasVerification = new AtlasVerification(expectedAtlasAddr); + factoryLib = new FactoryLib(address(execEnvTemplate)); // Deploy the Atlas contract with correct parameters atlas = new Atlas({ escrowDuration: 64, + atlasSurchargeRate: DEFAULT_ATLAS_SURCHARGE_RATE, + bundlerSurchargeRate: DEFAULT_BUNDLER_SURCHARGE_RATE, verification: address(atlasVerification), simulator: address(0), - executionTemplate: address(execEnvTemplate), + factoryLib: address(factoryLib), initialSurchargeRecipient: atlasDeployer, l2GasCalculator: address(0) }); diff --git a/test/Escrow.t.sol b/test/Escrow.t.sol index 31970c418..88ee6602e 100644 --- a/test/Escrow.t.sol +++ b/test/Escrow.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import { EscrowBits } from "src/contracts/libraries/EscrowBits.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; +import { IAtlas } from "../src/contracts/interfaces/IAtlas.sol"; +import { IDAppControl } from "../src/contracts/interfaces/IDAppControl.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; +import { CallBits } from "../src/contracts/libraries/CallBits.sol"; +import { EscrowBits } from "../src/contracts/libraries/EscrowBits.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; import { DummyDAppControl } from "./base/DummyDAppControl.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; @@ -22,11 +22,11 @@ import { SolverOperationBuilder } from "./base/builders/SolverOperationBuilder.s import { DAppOperationBuilder } from "./base/builders/DAppOperationBuilder.sol"; import { GasSponsorDAppControl } from "./base/GasSponsorDAppControl.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; +import "../src/contracts/types/UserOperation.sol"; +import "../src/contracts/types/SolverOperation.sol"; +import "../src/contracts/types/DAppOperation.sol"; +import "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/EscrowTypes.sol"; contract EscrowTest is BaseTest { using CallBits for CallConfig; @@ -42,11 +42,6 @@ contract EscrowTest is BaseTest { uint256 private constant _SOLVER_GAS_BUFFER = 5; // out of 100 uint256 private constant _FASTLANE_GAS_BUFFER = 125_000; // integer amount - event MEVPaymentSuccess(address bidToken, uint256 bidAmount); - event SolverTxResult( - address indexed solverTo, address indexed solverFrom, bool executed, bool success, uint256 result - ); - function defaultCallConfig() public returns (CallConfigBuilder) { return new CallConfigBuilder(); } @@ -144,7 +139,10 @@ contract EscrowTest is BaseTest { .withAllowAllocateValueFailure(true) // Allow the value allocation to fail .build() ); - executeHookCase(false, block.timestamp * 2, noError); + + (UserOperation memory userOp,,) = executeHookCase(block.timestamp * 2, noError); + bytes memory expectedInput = abi.encode(userOp); + assertEq(expectedInput, dAppControl.preOpsInputData(), "preOpsInputData should match expectedInput"); } // Ensure metacall reverts with the proper error when the preOps hook reverts. @@ -155,7 +153,8 @@ contract EscrowTest is BaseTest { .withReuseUserOp(true) // Allow metacall to revert .build() ); - executeHookCase(true, 0, AtlasErrors.PreOpsFail.selector); + dAppControl.setPreOpsShouldRevert(true); + executeHookCase(0, AtlasErrors.PreOpsFail.selector); } // Ensure the user operation executes successfully. To ensure the operation's returned data is as expected, we @@ -169,7 +168,9 @@ contract EscrowTest is BaseTest { .withAllowAllocateValueFailure(true) // Allow the value allocation to fail .build() ); - executeHookCase(false, block.timestamp * 3, noError); + executeHookCase(block.timestamp * 3, noError); + bytes memory expectedInput = abi.encode(block.timestamp * 3); + assertEq(expectedInput, dAppControl.userOpInputData(), "userOpInputData should match expectedInput"); } // Ensure metacall reverts with the proper error when the user operation reverts. @@ -179,7 +180,68 @@ contract EscrowTest is BaseTest { .withReuseUserOp(true) // Allow metacall to revert .build() ); - executeHookCase(true, 0, AtlasErrors.UserOpFail.selector); + dAppControl.setUserOpShouldRevert(true); + executeHookCase(0, AtlasErrors.UserOpFail.selector); + } + + function test_executeUserOperation_enforcesUserOpGasLimit() public { + uint256 userGasLim = 123_456; // default is 1 million in other tests in this file + + // First do metacall with default userOp gas limit (1 million) + defaultAtlasWithCallConfig(defaultCallConfig().build()); + executeHookCase(1, noError); + assertGt(dAppControl.userOpGasLeft(), userGasLim, "userOpGasLeft should be > userGasLim"); + + // Now do metacall with way lower gas limit (123_456) + vm.roll(block.number + 1); + UserOperation memory userOp = validUserOperation(address(dAppControl)) + .withData( + abi.encodeWithSelector( + dAppControl.userOperationCall.selector, + 1 + ) + ).withGas(userGasLim) + .signAndBuild(address(atlasVerification), userPK); + deal(address(dummySolver), defaultBidAmount); + SolverOperation[] memory solverOps = new SolverOperation[](1); + solverOps[0] = validSolverOperation(userOp) + .withBidAmount(defaultBidAmount) + .withData(abi.encode(1)) + .signAndBuild(address(atlasVerification), solverOnePK); + DAppOperation memory dappOp = validDAppOperation(userOp, solverOps).build(); + + vm.prank(userEOA); + bool auctionWon = atlas.metacall(userOp, solverOps, dappOp); + + assertLe(dAppControl.userOpGasLeft(), userGasLim, "userOpGasLeft should be <= userGasLim"); + assertTrue(auctionWon, "2nd auction should have been won"); + } + + function test_executeUserOperation_gracefullyReturnsWhenUserOpOOG() public { + // userOp.gas should be more than ceiling calculated in _executeUserOperation() + uint256 userGasLim = 500_000; + uint256 metacallGasLim = 300_000; // will trigger use of userOp gas ceiling + + defaultAtlasWithCallConfig(defaultCallConfig().build()); + UserOperation memory userOp = validUserOperation(address(dAppControl)) + .withData( + abi.encodeWithSelector( + dAppControl.burnEntireGasLimit.selector) + ).withGas(userGasLim) + .signAndBuild(address(atlasVerification), userPK); + deal(address(dummySolver), defaultBidAmount); + SolverOperation[] memory solverOps = new SolverOperation[](1); + solverOps[0] = validSolverOperation(userOp) + .withBidAmount(defaultBidAmount) + .withData(abi.encode(1)) + .signAndBuild(address(atlasVerification), solverOnePK); + DAppOperation memory dappOp = validDAppOperation(userOp, solverOps).build(); + + // Send msg.value so it must be sent back, testing the upper bound of remaining gas for graceful return + deal(userEOA, 1 ether); + vm.prank(userEOA); + bool auctionWon = atlas.metacall{gas: metacallGasLim, value: 1 ether}(userOp, solverOps, dappOp); + assertEq(auctionWon, false, "call should not revert but auction should not be won either"); } // Ensure metacall reverts with the proper error when the allocateValue hook reverts. @@ -192,7 +254,9 @@ contract EscrowTest is BaseTest { .withAllowAllocateValueFailure(false) // Do not allow the value allocation to fail .build() ); - executeHookCase(false, 1, AtlasErrors.AllocateValueFail.selector); + + dAppControl.setAllocateValueShouldRevert(true); + executeHookCase(1, AtlasErrors.AllocateValueFail.selector); } // Ensure the postOps hook is successfully called. No return data is expected from the postOps hook, so we do not @@ -203,7 +267,9 @@ contract EscrowTest is BaseTest { .withRequirePostOps(true) // Execute the postOps hook .build() ); - executeHookCase(false, 0, noError); + executeHookCase(0, noError); + bytes memory expectedInput = abi.encode(true, new bytes(0)); + assertEq(expectedInput, dAppControl.postOpsInputData(), "postOpsInputData should match expectedInput"); } // Ensure metacall reverts with the proper error when the postOps hook reverts. @@ -217,7 +283,8 @@ contract EscrowTest is BaseTest { .withAllowAllocateValueFailure(true) // Allow the value allocation to fail .build() ); - executeHookCase(false, 1, AtlasErrors.PostOpsFail.selector); + dAppControl.setPostOpsShouldRevert(true); + executeHookCase(1, AtlasErrors.PostOpsFail.selector); } // Ensure the allocateValue hook is successfully called. No return data is expected from the allocateValue hook, so @@ -229,35 +296,37 @@ contract EscrowTest is BaseTest { .withTrackUserReturnData(true) // Track the user operation's return data .build() ); + uint256 userOpArg = 321; - vm.prank(userEOA); - address executionEnvironment = atlas.createExecutionEnvironment(userEOA, address(dAppControl)); + executeHookCase(userOpArg, noError); - vm.expectEmit(false, false, false, true, executionEnvironment); - emit MEVPaymentSuccess(address(0), defaultBidAmount); - this.executeHookCase(false, 0, noError); + bytes memory expectedInput = abi.encode(address(0), defaultBidAmount, abi.encode(userOpArg)); + assertEq(expectedInput, dAppControl.allocateValueInputData(), "allocateValueInputData should match expectedInput"); } - function executeHookCase(bool hookShouldRevert, uint256 expectedHookReturnValue, bytes4 expectedError) public { + function executeHookCase(uint256 expectedHookReturnValue, bytes4 expectedError) public returns( + UserOperation memory userOp, + SolverOperation[] memory solverOps, + DAppOperation memory dappOp + ) { bool revertExpected = expectedError != noError; - UserOperation memory userOp = validUserOperation(address(dAppControl)) + userOp = validUserOperation(address(dAppControl)) .withData( abi.encodeWithSelector( dAppControl.userOperationCall.selector, - hookShouldRevert, expectedHookReturnValue ) ) .signAndBuild(address(atlasVerification), userPK); - SolverOperation[] memory solverOps = new SolverOperation[](1); + solverOps = new SolverOperation[](1); solverOps[0] = validSolverOperation(userOp) .withBidAmount(defaultBidAmount) .withData(abi.encode(expectedHookReturnValue)) .signAndBuild(address(atlasVerification), solverOnePK); - DAppOperation memory dappOp = validDAppOperation(userOp, solverOps).build(); + dappOp = validDAppOperation(userOp, solverOps).build(); if (revertExpected) { vm.expectRevert(expectedError); @@ -305,7 +374,7 @@ contract EscrowTest is BaseTest { .withGas(solverGasLimit) .signAndBuild(address(atlasVerification), solverOnePK); - executeSolverOperationCase(userOp, solverOps, false, false, 1 << uint256(SolverOutcome.InsufficientEscrow), true); + executeSolverOperationCase(userOp, solverOps, false, false, 1 << uint256(SolverOutcome.InsufficientEscrow), false); } function test_executeSolverOperation_validateSolverOperation_callValueTooHigh_SkipCoverage() public { @@ -324,7 +393,7 @@ contract EscrowTest is BaseTest { function test_executeSolverOperation_validateSolverOperation_userOutOfGas_SkipCoverage() public { (UserOperation memory userOp, SolverOperation[] memory solverOps) = executeSolverOperationInit(defaultCallConfig().build()); this.executeSolverOperationCase{gas: _VALIDATION_GAS_LIMIT + _SOLVER_GAS_LIMIT + 1_000_000}( - userOp, solverOps, false, false, 1 << uint256(SolverOutcome.UserOutOfGas), true + userOp, solverOps, false, false, 1 << uint256(SolverOutcome.UserOutOfGas), false ); } @@ -383,7 +452,7 @@ contract EscrowTest is BaseTest { ); UserOperation memory userOp = validUserOperation(address(dAppControl)) - .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, false, 1)) + .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, 1)) .signAndBuild(address(atlasVerification), userPK); SolverOperation[] memory solverOps = new SolverOperation[](1); @@ -392,6 +461,8 @@ contract EscrowTest is BaseTest { .signAndBuild(address(atlasVerification), solverOnePK); uint256 result = (1 << uint256(SolverOutcome.PreSolverFailed)); + dAppControl.setPreSolverShouldRevert(true); + executeSolverOperationCase(userOp, solverOps, false, false, result, true); } @@ -407,7 +478,7 @@ contract EscrowTest is BaseTest { ); UserOperation memory userOp = validUserOperation(address(dAppControl)) - .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, false, 1)) + .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, 1)) .signAndBuild(address(atlasVerification), userPK); SolverOperation[] memory solverOps = new SolverOperation[](1); @@ -416,6 +487,8 @@ contract EscrowTest is BaseTest { .signAndBuild(address(atlasVerification), solverOnePK); uint256 result = (1 << uint256(SolverOutcome.PostSolverFailed)); + dAppControl.setPostSolverShouldRevert(true); + executeSolverOperationCase(userOp, solverOps, true, false, result, true); } @@ -464,11 +537,6 @@ contract EscrowTest is BaseTest { .withBidAmount(bidAmount) .signAndBuild(address(atlasVerification), solverOnePK); - console.log("DApp control balance", address(gasSponsorControl).balance); - console.log("Solver balance", address(dummySolver).balance); - console.log("Bid amount (to trigger partial)", bidAmount); - console.log("Solver bonded amt", atlas.balanceOfBonded(solverOneEOA)); - uint256 expectedResult = 0; // Success expected executeSolverOperationCase(userOp, solverOps, true, true, expectedResult, false); } @@ -480,7 +548,6 @@ contract EscrowTest is BaseTest { uint256 solverOpValue = address(atlas).balance; assertTrue(solverOpValue > 0, "solverOpValue must be greater than 0"); - deal(address(solver), 10e18); // plenty of ETH to repay what solver owes (UserOperation memory userOp, SolverOperation[] memory solverOps) = executeSolverOperationInit(defaultCallConfig().build()); @@ -496,6 +563,67 @@ contract EscrowTest is BaseTest { assertTrue(success, "metacall should have succeeded"); } + function test_executeSolverOperation_ForwardReturnData_True() public { + // Checks that the solver CAN receive the data returned from the userOp phase + uint256 expectedDataValue = 123; + DummySolverContributor solver = new DummySolverContributor(address(atlas)); + assertEq(solver.forwardedData().length, 0, "solver forwardedData should start empty"); + deal(address(solver), 1 ether); // 1 ETH covers default bid (1) + 0.5 ETH gas cost + + (UserOperation memory userOp, SolverOperation[] memory solverOps) = executeSolverOperationInit( + defaultCallConfig() + .withTrackUserReturnData(true) + .withForwardReturnData(true) + .withRequireFulfillment(true) + .build() + ); + + userOp = validUserOperation(address(dAppControl)) + .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, expectedDataValue)) + .signAndBuild(address(atlasVerification), userPK); + + solverOps[0] = validSolverOperation(userOp) + .withSolver(address(solver)) + .withBidAmount(defaultBidAmount) + .signAndBuild(address(atlasVerification), solverOnePK); + + uint256 result = 0; // Success + executeSolverOperationCase(userOp, solverOps, true, true, result, false); + + uint256 forwardedData = abi.decode(solver.forwardedData(), (uint256)); + assertEq(forwardedData, expectedDataValue, "solver should have received the userOp data"); + } + + function test_executeSolverOperation_ForwardReturnData_False() public { + // Checks that the solver CANNOT receive the data returned from the userOp phase + uint256 dataValue = 123; + DummySolverContributor solver = new DummySolverContributor(address(atlas)); + assertEq(solver.forwardedData().length, 0, "solver forwardedData should start empty"); + deal(address(solver), 1 ether); // 1 ETH covers default bid (1) + 0.5 ETH gas cost + + (UserOperation memory userOp, SolverOperation[] memory solverOps) = executeSolverOperationInit( + defaultCallConfig() + .withTrackUserReturnData(true) + .withForwardReturnData(false) + .withRequireFulfillment(true) + .build() + ); + + userOp = validUserOperation(address(dAppControl)) + .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, dataValue)) + .signAndBuild(address(atlasVerification), userPK); + + solverOps[0] = validSolverOperation(userOp) + .withSolver(address(solver)) + .withBidAmount(defaultBidAmount) + .signAndBuild(address(atlasVerification), solverOnePK); + + uint256 result = 0; // Success + executeSolverOperationCase(userOp, solverOps, true, true, result, false); + assertEq(solver.forwardedData().length, 0, "solver forwardedData should still be empty"); + } + + function test_executeSolverOperation_solverOpWrapper_defaultCase() public { // Can't find a way to reach the default case (which is a good thing) vm.skip(true); @@ -508,7 +636,7 @@ contract EscrowTest is BaseTest { defaultAtlasWithCallConfig(callConfig); userOp = validUserOperation(address(dAppControl)) - .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, false, 0)) + .withData(abi.encodeWithSelector(dAppControl.userOperationCall.selector, 0)) .signAndBuild(address(atlasVerification), userPK); solverOps = new SolverOperation[](1); @@ -530,7 +658,16 @@ contract EscrowTest is BaseTest { DAppOperation memory dappOp = validDAppOperation(userOp, solverOps).build(); vm.expectEmit(false, false, false, true, address(atlas)); - emit SolverTxResult(solverOps[0].solver, solverOps[0].from, solverOpExecuted, solverOpSuccess, expectedResult); + emit AtlasEvents.SolverTxResult( + solverOps[0].solver, + solverOps[0].from, + userOp.control, + solverOps[0].bidToken, + solverOps[0].bidAmount, + solverOpExecuted, + solverOpSuccess, + expectedResult + ); vm.prank(userEOA); if (metacallShouldRevert) vm.expectRevert(); // Metacall should revert, the reason isn't important, we're only checking the event @@ -548,7 +685,7 @@ contract DummySolver { } function atlasSolverCall( - address solverOpFrom, + address /* solverOpFrom */, address executionEnvironment, address, uint256 bidAmount, @@ -568,7 +705,6 @@ contract DummySolver { if (address(this).balance >= bidAmount) { SafeTransferLib.safeTransferETH(executionEnvironment, bidAmount); } - if (bidAmount == noGasPayBack) { // Don't pay gas @@ -576,10 +712,6 @@ contract DummySolver { } else if (bidAmount == partialGasPayBack) { // Only pay half of shortfall owed - expect postSolverCall hook in DAppControl to pay the rest uint256 _shortfall = IAtlas(_atlas).shortfall(); - - console.log("Solver shortfall", _shortfall); - console.log("gas price", tx.gasprice); - IAtlas(_atlas).reconcile(_shortfall / 2); return; } @@ -592,31 +724,34 @@ contract DummySolver { } contract DummySolverContributor { - address private _atlas; + address private immutable ATLAS; + bytes public forwardedData; constructor(address atlas) { - _atlas = atlas; + ATLAS = atlas; } function atlasSolverCall( - address solverOpFrom, + address /* solverOpFrom */, address executionEnvironment, address, uint256 bidAmount, bytes calldata, - bytes calldata + bytes calldata userReturnData ) external payable { + if (userReturnData.length > 0) forwardedData = userReturnData; + // Pay bid if (address(this).balance >= bidAmount) { SafeTransferLib.safeTransferETH(executionEnvironment, bidAmount); } // Pay borrowed ETH + gas used - uint256 shortfall = IAtlas(_atlas).shortfall(); - IAtlas(_atlas).reconcile{value: shortfall}(0); + uint256 shortfall = IAtlas(ATLAS).shortfall(); + IAtlas(ATLAS).reconcile{value: shortfall}(0); return; } diff --git a/test/ExPost.t.sol b/test/ExPost.t.sol index 49dc800c2..78f5add99 100644 --- a/test/ExPost.t.sol +++ b/test/ExPost.t.sol @@ -1,31 +1,27 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; + +import "forge-std/Test.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; - -import { Atlas } from "src/contracts/atlas/Atlas.sol"; - -import { Result } from "src/contracts/helpers/Simulator.sol"; - -import { V2ExPost } from "src/contracts/examples/ex-post-mev-example/V2ExPost.sol"; +import { IExecutionEnvironment } from "../src/contracts/interfaces/IExecutionEnvironment.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { Result } from "../src/contracts/helpers/Simulator.sol"; +import { V2ExPost } from "../src/contracts/examples/ex-post-mev-example/V2ExPost.sol"; +import { SolverExPost } from "../src/contracts/solver/src/TestSolverExPost.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; -import { SolverExPost } from "src/contracts/solver/src/TestSolverExPost.sol"; - -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/UserOperation.sol"; +import "../src/contracts/types/SolverOperation.sol"; +import "../src/contracts/types/EscrowTypes.sol"; +import "../src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; +import "../src/contracts/types/ConfigTypes.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; import { V2Helper } from "./V2Helper.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; - -import "forge-std/Test.sol"; contract ExPostTest is BaseTest { /// forge-config: default.gas_price = 15000000000 @@ -143,11 +139,6 @@ contract ExPostTest is BaseTest { address executionEnvironment = atlas.createExecutionEnvironment(userEOA, userOp.control); vm.label(address(executionEnvironment), "EXECUTION ENV"); - console.log("userEOA", userEOA); - console.log("atlas", address(atlas)); - console.log("v2 ExPost Control", address(v2ExPost)); - console.log("executionEnvironment", executionEnvironment); - // User must approve Atlas IERC20(TOKEN_ZERO).approve(address(atlas), type(uint256).max); IERC20(TOKEN_ONE).approve(address(atlas), type(uint256).max); @@ -366,8 +357,6 @@ contract ExPostTest is BaseTest { (bool success,) = address(atlas).call(abi.encodeWithSelector(atlas.metacall.selector, userOp, solverOps, dAppOp)); console.log("Metacall Gas Cost:", gasLeftBefore - gasleft()); - if (success) console.log("success!"); - else console.log("failure"); assertTrue(success); vm.stopPrank(); } diff --git a/test/ExecutionBase.t.sol b/test/ExecutionBase.t.sol index 5cb1a0b11..b30d6d542 100644 --- a/test/ExecutionBase.t.sol +++ b/test/ExecutionBase.t.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { Base } from "src/contracts/common/ExecutionBase.sol"; -import { ExecutionPhase } from "src/contracts/types/LockTypes.sol"; +import { Base } from "../src/contracts/common/ExecutionBase.sol"; +import { ExecutionPhase } from "../src/contracts/types/LockTypes.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; +import { SafetyBits } from "../src/contracts/libraries/SafetyBits.sol"; -import "src/contracts/libraries/SafetyBits.sol"; +import "../src/contracts/libraries/SafetyBits.sol"; contract ExecutionBaseTest is BaseTest { using SafetyBits for Context; diff --git a/test/ExecutionEnvironment.t.sol b/test/ExecutionEnvironment.t.sol index 5162118b3..e7bac6f64 100644 --- a/test/ExecutionEnvironment.t.sol +++ b/test/ExecutionEnvironment.t.sol @@ -1,30 +1,30 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; import { MockSafetyLocks } from "./SafetyLocks.t.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { ExecutionEnvironment } from "../src/contracts/common/ExecutionEnvironment.sol"; +import { DAppControl } from "../src/contracts/dapp/DAppControl.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IAtlas } from "../src/contracts/interfaces/IAtlas.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; +import { SafetyBits } from "../src/contracts/libraries/SafetyBits.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; +import "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/UserOperation.sol"; +import "../src/contracts/types/SolverOperation.sol"; +import "../src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/EscrowTypes.sol"; -import "src/contracts/libraries/CallBits.sol"; +import "../src/contracts/libraries/CallBits.sol"; /// @notice ExecutionEnvironmentTest tests deploy ExecutionEnvironment contracts through the factory. Because all calls /// are delegated through the mimic contract, the reported coverage is at 0%, but the actual coverage is close to 100%. diff --git a/test/FLOnline.t.sol b/test/FLOnline.t.sol index 082507d48..c8f9ab6e9 100644 --- a/test/FLOnline.t.sol +++ b/test/FLOnline.t.sol @@ -1,21 +1,21 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; -import { FastLaneOnlineOuter } from "src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol"; -import { FastLaneOnlineInner } from "src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol"; -import { SwapIntent, BaselineCall, Reputation } from "src/contracts/examples/fastlane-online/FastLaneTypes.sol"; -import { FastLaneOnlineErrors } from "src/contracts/examples/fastlane-online/FastLaneOnlineErrors.sol"; +import { FastLaneOnlineOuter } from "../src/contracts/examples/fastlane-online/FastLaneOnlineOuter.sol"; +import { FastLaneOnlineInner } from "../src/contracts/examples/fastlane-online/FastLaneOnlineInner.sol"; +import { SwapIntent, BaselineCall, Reputation } from "../src/contracts/examples/fastlane-online/FastLaneTypes.sol"; +import { FastLaneOnlineErrors } from "../src/contracts/examples/fastlane-online/FastLaneOnlineErrors.sol"; -import { IUniswapV2Router02 } from "test/base/interfaces/IUniswapV2Router.sol"; +import { IUniswapV2Router02 } from "./base/interfaces/IUniswapV2Router.sol"; contract FastLaneOnlineTest is BaseTest { struct FastOnlineSwapArgs { @@ -51,7 +51,9 @@ contract FastLaneOnlineTest is BaseTest { bool solverFour; } - uint256 constant ERR_MARGIN = 0.15e18; // 15% error margin + // Only Atlas surcharge kept if all fail, bundler surcharge paid to bundler + uint256 constant SURCHARGE_PER_SOLVER_IF_ALL_FAIL = 14_000e9; // 14k Gwei (avg, differs for ERC20/native in/out) + uint256 constant ERR_MARGIN = 0.22e18; // 22% error margin address internal constant NATIVE_TOKEN = address(0); address protocolGuildWallet = 0x25941dC771bB64514Fc8abBce970307Fb9d477e9; @@ -60,7 +62,6 @@ contract FastLaneOnlineTest is BaseTest { uint256 goodSolverBidETH = 1.2 ether; // more than baseline swap amountOut if tokenOut is WETH/ETH uint256 goodSolverBidDAI = 3100e18; // more than baseline swap amountOut if tokenOut is DAI - uint256 defaultMsgValue = 1e16; // 0.01 ETH for bundler gas, treated as donation uint256 defaultGasLimit = 2_000_000; uint256 defaultGasPrice; uint256 defaultDeadlineBlock; @@ -1279,7 +1280,6 @@ contract FastLaneOnlineTest is BaseTest { internal { bool nativeTokenIn = args.swapIntent.tokenUserSells == NATIVE_TOKEN; - bool nativeTokenOut = args.swapIntent.tokenUserBuys == NATIVE_TOKEN; bool solverWon = winningSolver != address(0); beforeVars.userTokenOutBalance = _balanceOf(args.swapIntent.tokenUserBuys, userEOA); @@ -1291,9 +1291,6 @@ contract FastLaneOnlineTest is BaseTest { beforeVars.solverTwoRep = flOnline.solverReputation(solverTwoEOA); beforeVars.solverThreeRep = flOnline.solverReputation(solverThreeEOA); - // adjust userTokenInBalance if native token - exclude gas treated as donation - if (nativeTokenIn) beforeVars.userTokenInBalance -= defaultMsgValue; - uint256 txGasUsed; uint256 estAtlasGasSurcharge = gasleft(); // Reused below during calculations @@ -1315,13 +1312,26 @@ contract FastLaneOnlineTest is BaseTest { // Return early if transaction expected to revert. Balance checks below would otherwise fail. if (!swapCallShouldSucceed) return; - // Check Atlas gas surcharge earned is within 15% of the estimated gas surcharge - assertApproxEqRel( - atlas.cumulativeSurcharge() - beforeVars.atlasGasSurcharge, - estAtlasGasSurcharge, - ERR_MARGIN, - "Atlas gas surcharge not within estimated range" - ); + if (solverCount == 0) { + // If zero solvers, no surcharge taken + assertEq(atlas.cumulativeSurcharge(), beforeVars.atlasGasSurcharge, "Atlas gas surcharge should not change"); + } else if (solverWon) { + // Check Atlas gas surcharge earned is within 15% of the estimated gas surcharge + assertApproxEqRel( + atlas.cumulativeSurcharge() - beforeVars.atlasGasSurcharge, + estAtlasGasSurcharge, + ERR_MARGIN, + "Atlas gas surcharge not within estimated range (solver won)" + ); + } else { + // If all solvers fail, surcharge taken only on gas cost of solverOps failed due to solver fault + assertApproxEqRel( + atlas.cumulativeSurcharge() - beforeVars.atlasGasSurcharge, + SURCHARGE_PER_SOLVER_IF_ALL_FAIL * solverCount, + ERR_MARGIN, + "Atlas gas surcharge not within estimated range (solvers failed)" + ); + } // Check user's balances changed as expected assertTrue( @@ -1446,10 +1456,9 @@ contract FastLaneOnlineTest is BaseTest { newArgs.deadline = defaultDeadlineBlock; newArgs.gas = defaultGasLimit; newArgs.maxFeePerGas = defaultGasPrice; - newArgs.msgValue = defaultMsgValue; // Add amountUserSells of ETH to the msg.value of the fastOnlineSwap call - if (nativeTokenIn) newArgs.msgValue += swapIntent.amountUserSells; + if (nativeTokenIn) newArgs.msgValue = swapIntent.amountUserSells; } function _buildBaselineCall( diff --git a/test/Factory.t.sol b/test/Factory.t.sol index 814db49c3..7abe3a375 100644 --- a/test/Factory.t.sol +++ b/test/Factory.t.sol @@ -1,22 +1,23 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { Factory } from "src/contracts/atlas/Factory.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; +import { Factory } from "../src/contracts/atlas/Factory.sol"; +import { FactoryLib } from "../src/contracts/atlas/FactoryLib.sol"; +import { ExecutionEnvironment } from "../src/contracts/common/ExecutionEnvironment.sol"; import { DummyDAppControl, CallConfigBuilder } from "./base/DummyDAppControl.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; -import "src/contracts/types/UserOperation.sol"; +import "../src/contracts/types/UserOperation.sol"; import "./base/TestUtils.sol"; -contract MockFactory is Factory, Test { - constructor(address _executionTemplate) Factory(_executionTemplate) { } +contract MockFactory is Factory { + constructor(address factoryLib) Factory(factoryLib) { } function getOrCreateExecutionEnvironment(UserOperation calldata userOp) external @@ -32,6 +33,10 @@ contract MockFactory is Factory, Test { function baseSalt() external view returns (bytes32) { return _FACTORY_BASE_SALT; } +} + +contract MockFactoryLib is FactoryLib { + constructor(address executionTemplate) FactoryLib(executionTemplate) { } function getMimicCreationCode( address user, @@ -40,16 +45,20 @@ contract MockFactory is Factory, Test { ) external view - returns (bytes memory creationCode) { - require(EXECUTION_ENV_TEMPLATE != address(0), "TEST: Execution environment template not set"); - return _getMimicCreationCode(user, control, callConfig); - } + returns (bytes memory) + { + return _getMimicCreationCode(user, control, callConfig); + } } contract FactoryTest is Test { + uint256 DEFAULT_ATLAS_SURCHARGE_RATE = 1_000_000; // 10% + uint256 DEFAULT_BUNDLER_SURCHARGE_RATE = 1_000_000; // 10% + Atlas public atlas; AtlasVerification public atlasVerification; MockFactory public mockFactory; + MockFactoryLib public factoryLib; DummyDAppControl public dAppControl; address public user; @@ -57,33 +66,44 @@ contract FactoryTest is Test { function setUp() public { user = address(999); address deployer = address(333); - address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 0); - address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 1); - address expectedFactoryAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); - bytes32 salt = keccak256(abi.encodePacked(block.chainid, expectedFactoryAddr)); - ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment{ salt: salt }(expectedFactoryAddr); - + + address expectedFactoryLibAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 1); + address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); + address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 3); + address expectedFactoryAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 4); + vm.startPrank(deployer); + ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment(expectedFactoryAddr); + + factoryLib = new MockFactoryLib(address(execEnvTemplate)); + assertEq(address(factoryLib), expectedFactoryLibAddr, "FactoryLib address mismatch"); + atlas = new Atlas({ escrowDuration: 64, + atlasSurchargeRate: DEFAULT_ATLAS_SURCHARGE_RATE, + bundlerSurchargeRate: DEFAULT_BUNDLER_SURCHARGE_RATE, verification: expectedAtlasVerificationAddr, simulator: address(0), - executionTemplate: address(execEnvTemplate), + factoryLib: address(factoryLib), initialSurchargeRecipient: deployer, l2GasCalculator: address(0) }); assertEq(address(atlas), expectedAtlasAddr, "Atlas address mismatch"); + atlasVerification = new AtlasVerification(address(atlas)); assertEq(address(atlasVerification), expectedAtlasVerificationAddr, "AtlasVerification address mismatch"); - mockFactory = new MockFactory({ _executionTemplate: address(execEnvTemplate) }); + + mockFactory = new MockFactory({ factoryLib: address(factoryLib) }); assertEq(address(mockFactory), expectedFactoryAddr, "Factory address mismatch"); + dAppControl = new DummyDAppControl(expectedAtlasAddr, deployer, CallConfigBuilder.allFalseCallConfig()); vm.stopPrank(); } function test_createExecutionEnvironment() public { uint32 callConfig = dAppControl.CALL_CONFIG(); - bytes memory creationCode = mockFactory.getMimicCreationCode(user, address(dAppControl), callConfig); + // NOTE: getMimicCreationCode is now in FactoryLib + bytes memory creationCode = factoryLib.getMimicCreationCode(user, address(dAppControl), callConfig); address expectedExecutionEnvironment = address( uint160( uint256( @@ -147,7 +167,7 @@ contract FactoryTest is Test { assertEq(predictedEE, actualEE, "Predicted and actual EE addrs should match 2"); (predictedEE,, exists) = mockFactory.getExecutionEnvironment(user, address(dAppControl)); - + assertTrue(exists, "Execution environment should exist - exist should return true"); assertFalse(predictedEE.code.length == 0, "Execution environment should exist - code at addr"); assertEq(predictedEE, actualEE, "Predicted and actual EE addrs should match 2"); @@ -162,6 +182,10 @@ contract FactoryTest is Test { uint32 _callConfig = 789; bytes32 expectedComputeSalt = keccak256(abi.encodePacked(baseSalt, _user, _control, _callConfig)); - assertEq(expectedComputeSalt, mockFactory.computeSalt(_user, _control, _callConfig), "user salt not computed correctly - depends on base salt"); + assertEq( + expectedComputeSalt, + mockFactory.computeSalt(_user, _control, _callConfig), + "user salt not computed correctly - depends on base salt" + ); } } diff --git a/test/FlashLoan.t.sol b/test/FlashLoan.t.sol index 9b5fc273b..b864ec0ef 100644 --- a/test/FlashLoan.t.sol +++ b/test/FlashLoan.t.sol @@ -1,36 +1,44 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; import { ArbitrageTest } from "./base/ArbitrageTest.t.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import { SolverOutcome } from "src/contracts/types/EscrowTypes.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/DAppOperation.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; +import { DAppControl } from "../src/contracts/dapp/DAppControl.sol"; +import { CallConfig } from "../src/contracts/types/ConfigTypes.sol"; +import { SolverOutcome } from "../src/contracts/types/EscrowTypes.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { DAppOperation } from "../src/contracts/types/DAppOperation.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; +import { IAtlas } from "../src/contracts/interfaces/IAtlas.sol"; import { UserOperationBuilder } from "./base/builders/UserOperationBuilder.sol"; import { SolverOperationBuilder } from "./base/builders/SolverOperationBuilder.sol"; import { DAppOperationBuilder } from "./base/builders/DAppOperationBuilder.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; interface IWETH { function withdraw(uint256 wad) external; } +struct Balances{ + uint256 eth; + uint256 atlETH; + uint256 bonded; +} + contract FlashLoanTest is BaseTest { DummyDAppControlBuilder public control; Sig public sig; + Balances public userBefore; + Balances public userAfter; function setUp() public virtual override { BaseTest.setUp(); @@ -111,7 +119,16 @@ contract FlashLoanTest is BaseTest { vm.startPrank(userEOA); vm.expectEmit(true, true, true, true); uint256 result = (1 << uint256(SolverOutcome.BidNotPaid)); - emit AtlasEvents.SolverTxResult(address(solver), solverOneEOA, true, false, result); + emit AtlasEvents.SolverTxResult( + address(solver), + solverOneEOA, + userOp.control, + solverOps[0].bidToken, + solverOps[0].bidAmount, + true, + false, + result + ); vm.expectRevert(); atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp }); vm.stopPrank(); @@ -154,7 +171,16 @@ contract FlashLoanTest is BaseTest { vm.expectEmit(true, true, true, true); result = (1 << uint256(SolverOutcome.CallValueTooHigh)); console.log("result", result); - emit AtlasEvents.SolverTxResult(address(solver), solverOneEOA, false, false, result); + emit AtlasEvents.SolverTxResult( + address(solver), + solverOneEOA, + userOp.control, + solverOps[0].bidToken, + solverOps[0].bidAmount, + false, + false, + result + ); vm.expectRevert(); atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp }); vm.stopPrank(); @@ -193,15 +219,12 @@ contract FlashLoanTest is BaseTest { (sig.v, sig.r, sig.s) = vm.sign(governancePK, atlasVerification.getDAppOperationPayload(dAppOp)); dAppOp.signature = abi.encodePacked(sig.r, sig.s, sig.v); - address _solver = address(solver); - - uint256 solverStartingTotal = WETH.balanceOf(_solver); - + uint256 solverStartingTotal = WETH.balanceOf(address(solver)); uint256 atlasStartingETH = address(atlas).balance; - uint256 userStartingETH = address(userEOA).balance; - uint256 userStartingAtlETH = atlas.balanceOf(userEOA); - uint256 userStartingBonded = atlas.balanceOfBonded(userEOA); + userBefore.eth = address(userEOA).balance; + userBefore.atlETH = atlas.balanceOf(userEOA); + userBefore.bonded = atlas.balanceOfBonded(userEOA); assertEq(solverStartingTotal, 1e18, "solver incorrect starting WETH"); solverStartingTotal += (atlas.balanceOf(solverOneEOA) + atlas.balanceOfBonded(solverOneEOA)); @@ -214,7 +237,16 @@ contract FlashLoanTest is BaseTest { vm.startPrank(userEOA); result = 0; vm.expectEmit(true, true, true, true); - emit AtlasEvents.SolverTxResult(_solver, solverOneEOA, true, true, result); + emit AtlasEvents.SolverTxResult( + address(solver), + solverOneEOA, + userOp.control, + solverOps[0].bidToken, + solverOps[0].bidAmount, + true, + true, + result + ); atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp }); vm.stopPrank(); @@ -223,18 +255,18 @@ contract FlashLoanTest is BaseTest { { console.log("solverStartingTotal: ", solverStartingTotal); - console.log("solverEndingTotal : ", WETH.balanceOf(_solver) + atlas.balanceOf(solverOneEOA) + atlas.balanceOfBonded(solverOneEOA)); - solverStartingTotal -= (WETH.balanceOf(_solver) + atlas.balanceOf(solverOneEOA) + atlas.balanceOfBonded(solverOneEOA)); + console.log("solverEndingTotal : ", WETH.balanceOf(address(solver)) + atlas.balanceOf(solverOneEOA) + atlas.balanceOfBonded(solverOneEOA)); + solverStartingTotal -= (WETH.balanceOf(address(solver)) + atlas.balanceOf(solverOneEOA) + atlas.balanceOfBonded(solverOneEOA)); console.log("solverDeltaTotal : ", solverStartingTotal); } - uint256 userEndingETH = address(userEOA).balance; - uint256 userEndingAtlETH = atlas.balanceOf(userEOA); - uint256 userEndingBonded = atlas.balanceOfBonded(userEOA); + userAfter.eth = address(userEOA).balance; + userAfter.atlETH = atlas.balanceOf(userEOA); + userAfter.bonded = atlas.balanceOfBonded(userEOA); { - console.log("userStartingTotal :", userStartingETH + userStartingAtlETH + userStartingBonded); - console.log("userEndingTotal :", userEndingETH + userEndingAtlETH + userEndingBonded); + console.log("userStartingTotal :", userBefore.eth + userBefore.atlETH + userBefore.bonded); + console.log("userEndingTotal :", userAfter.eth + userAfter.atlETH + userAfter.bonded); console.log("atlasStartingETH :", atlasStartingETH); console.log("atlasEndingETH :", address(atlas).balance); @@ -243,7 +275,7 @@ contract FlashLoanTest is BaseTest { netSurcharge = atlas.cumulativeSurcharge() - netSurcharge; console.log("NetCumulativeSrchrg: ", netSurcharge); - assertEq(WETH.balanceOf(_solver), 0, "solver WETH not used"); + assertEq(WETH.balanceOf(address(solver)), 0, "solver WETH not used"); assertEq(atlas.balanceOf(solverOneEOA), 0, "solver atlETH not used"); console.log("atlasStartingETH :", atlasStartingETH); console.log("atlasEnding ETH :", address(atlas).balance); @@ -251,10 +283,10 @@ contract FlashLoanTest is BaseTest { // NOTE: solverStartingTotal is the solverTotal delta, not starting. assertTrue(address(atlas).balance >= atlasStartingETH - solverStartingTotal, "atlas incorrect ending ETH"); // atlas should NEVER lose balance during a metacall - console.log("userStartingETH :", userStartingETH); - console.log("userEndingETH :", userEndingETH); - assertTrue((userEndingETH - userStartingETH) >= 1 ether, "user incorrect ending ETH"); // user bal should increase by 1e (bid) + gas refund - assertTrue((userEndingBonded - userStartingBonded) == 0, "user incorrect ending bonded AtlETH"); // user bonded bal should increase by gas refund + console.log("userStartingETH :", userBefore.eth); + console.log("userEndingETH :", userAfter.eth); + assertTrue((userAfter.eth - userBefore.eth) >= 1 ether, "user incorrect ending ETH"); // user bal should increase by 1e (bid) + gas refund + assertTrue((userAfter.bonded - userBefore.bonded) == 0, "user incorrect ending bonded AtlETH"); // user bonded bal should increase by gas refund } } diff --git a/test/GasAccounting.t.sol b/test/GasAccounting.t.sol index cc57566ca..9952e48c0 100644 --- a/test/GasAccounting.t.sol +++ b/test/GasAccounting.t.sol @@ -1,43 +1,44 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { SafeCast } from "openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; -import { GasAccounting } from "src/contracts/atlas/GasAccounting.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { AtlasConstants } from "src/contracts/types/AtlasConstants.sol"; +import { GasAccounting } from "../src/contracts/atlas/GasAccounting.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; +import { AtlasConstants } from "../src/contracts/types/AtlasConstants.sol"; -import { EscrowBits } from "src/contracts/libraries/EscrowBits.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import { IL2GasCalculator } from "src/contracts/interfaces/IL2GasCalculator.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; +import { EscrowBits } from "../src/contracts/libraries/EscrowBits.sol"; +import { IL2GasCalculator } from "../src/contracts/interfaces/IL2GasCalculator.sol"; -import "src/contracts/libraries/AccountingMath.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/libraries/AccountingMath.sol"; +import "../src/contracts/types/EscrowTypes.sol"; +import "../src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/SolverOperation.sol"; +import "../src/contracts/types/ConfigTypes.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; +import { ExecutionEnvironment } from "../src/contracts/common/ExecutionEnvironment.sol"; -import { TestAtlas } from "test/base/TestAtlas.sol"; -import { BaseTest } from "test/base/BaseTest.t.sol"; +import { TestAtlas } from "./base/TestAtlas.sol"; +import { BaseTest } from "./base/BaseTest.t.sol"; contract MockGasAccounting is TestAtlas, BaseTest { uint256 public constant MOCK_SOLVER_GAS_LIMIT = 500_000; - constructor( uint256 _escrowDuration, + uint256 _atlasSurchargeRate, + uint256 _bundlerSurchargeRate, address _verification, address _simulator, address _surchargeRecipient, address _l2GasCalculator, address _executionTemplate ) - TestAtlas(_escrowDuration, _verification, _simulator, _surchargeRecipient, _l2GasCalculator, _executionTemplate) + TestAtlas(_escrowDuration, _atlasSurchargeRate, _bundlerSurchargeRate, _verification, _simulator, _surchargeRecipient, _l2GasCalculator, _executionTemplate) { } ///////////////////////////////////////////////////////// @@ -116,7 +117,7 @@ contract MockGasAccounting is TestAtlas, BaseTest { } function setSolverLock(address _solverFrom) external { - _setSolverLock(uint256(uint160(_solverFrom))); + t_solverLock = (uint256(uint160(_solverFrom))); } function _balanceOf(address account) external view returns (uint112, uint112) { @@ -173,14 +174,6 @@ contract MockGasAccounting is TestAtlas, BaseTest { function getFixedGasOffset() external pure returns (uint256) { return AccountingMath._FIXED_GAS_OFFSET; } - - function getAtlasSurchargeRate() external pure returns (uint256) { - return AccountingMath._ATLAS_SURCHARGE_RATE; - } - - function getBundlerSurchargeRate() external pure returns (uint256) { - return AccountingMath._BUNDLER_SURCHARGE_RATE; - } } contract MockGasCalculator is IL2GasCalculator, Test { @@ -213,6 +206,8 @@ contract GasAccountingTest is AtlasConstants, BaseTest { // Initialize MockGasAccounting mockGasAccounting = new MockGasAccounting( DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, address(atlasVerification), address(simulator), deployer, @@ -321,7 +316,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { // Verify the balances after contribution assertEq(address(mockGasAccounting).balance, contributeValue); - assertEq(mockGasAccounting.getDeposits(), contributeValue); + assertEq(mockGasAccounting.deposits(), contributeValue); } function test_multipleContributes() public { @@ -340,7 +335,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { // Verify the balances after the first contribution assertEq(address(mockGasAccounting).balance, firstContributeValue); - assertEq(mockGasAccounting.getDeposits(), firstContributeValue); + assertEq(mockGasAccounting.deposits(), firstContributeValue); // Perform the second valid contribute call vm.prank(executionEnvironment); @@ -348,7 +343,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { // Verify the balances after the second contribution assertEq(address(mockGasAccounting).balance, totalContributeValue); - assertEq(mockGasAccounting.getDeposits(), totalContributeValue); + assertEq(mockGasAccounting.deposits(), totalContributeValue); } function test_contribute_withZeroValue() public { @@ -364,7 +359,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { // Verify the balances after the contribution is zero assertEq(address(mockGasAccounting).balance, contributeValue); - assertEq(mockGasAccounting.getDeposits(), contributeValue); + assertEq(mockGasAccounting.deposits(), contributeValue); } function test_borrow_preOpsPhase() public { @@ -379,7 +374,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { assertEq( solverOneEOA.balance, borrowedAmount, "Execution environment balance should be equal to borrowed amount" ); - assertEq(borrowedAmount, mockGasAccounting.getWithdrawals(), "Withdrawals should be equal to borrowed amount"); + assertEq(borrowedAmount, mockGasAccounting.withdrawals(), "Withdrawals should be equal to borrowed amount"); } function test_borrow_userOperationPhase() public { @@ -396,7 +391,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { borrowedAmount, "Execution environment balance should be equal to borrowed amount" ); - assertEq(borrowedAmount, mockGasAccounting.getWithdrawals(), "Withdrawals should be equal to borrowed amount"); + assertEq(borrowedAmount, mockGasAccounting.withdrawals(), "Withdrawals should be equal to borrowed amount"); } function test_borrow_preSolverPhase() public { @@ -413,7 +408,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { borrowedAmount, "Execution environment balance should be equal to borrowed amount" ); - assertEq(borrowedAmount, mockGasAccounting.getWithdrawals(), "Withdrawals should be equal to borrowed amount"); + assertEq(borrowedAmount, mockGasAccounting.withdrawals(), "Withdrawals should be equal to borrowed amount"); } function test_borrow_solverOperationPhase() public { @@ -429,12 +424,12 @@ contract GasAccountingTest is AtlasConstants, BaseTest { borrowedAmount, "Execution environment balance should be equal to borrowed amount" ); - assertEq(borrowedAmount, mockGasAccounting.getWithdrawals(), "Withdrawals should be equal to borrowed amount"); + assertEq(borrowedAmount, mockGasAccounting.withdrawals(), "Withdrawals should be equal to borrowed amount"); } function test_borrow_postSolverPhase_reverts() public { uint256 borrowedAmount = 1e18; - uint256 withdrawalsBefore = mockGasAccounting.getWithdrawals(); + uint256 withdrawalsBefore = mockGasAccounting.withdrawals(); fundContract(borrowedAmount); mockGasAccounting.setLock(executionEnvironment, 0, uint8(ExecutionPhase.PostSolver)); @@ -443,12 +438,12 @@ contract GasAccountingTest is AtlasConstants, BaseTest { mockGasAccounting.borrow(borrowedAmount); assertEq(executionEnvironment.balance, 0, "Execution environment balance should remain zero"); - assertEq(withdrawalsBefore, mockGasAccounting.getWithdrawals(), "Withdrawals should remain unchanged"); + assertEq(withdrawalsBefore, mockGasAccounting.withdrawals(), "Withdrawals should remain unchanged"); } function test_borrow_allocateValuePhase_reverts() public { uint256 borrowedAmount = 1e18; - uint256 withdrawalsBefore = mockGasAccounting.getWithdrawals(); + uint256 withdrawalsBefore = mockGasAccounting.withdrawals(); fundContract(borrowedAmount); mockGasAccounting.setLock(executionEnvironment, 0, uint8(ExecutionPhase.AllocateValue)); @@ -457,12 +452,12 @@ contract GasAccountingTest is AtlasConstants, BaseTest { mockGasAccounting.borrow(borrowedAmount); assertEq(executionEnvironment.balance, 0, "Execution environment balance should remain zero"); - assertEq(withdrawalsBefore, mockGasAccounting.getWithdrawals(), "Withdrawals should remain unchanged"); + assertEq(withdrawalsBefore, mockGasAccounting.withdrawals(), "Withdrawals should remain unchanged"); } function test_borrow_postOpsPhase_reverts() public { uint256 borrowedAmount = 1e18; - uint256 withdrawalsBefore = mockGasAccounting.getWithdrawals(); + uint256 withdrawalsBefore = mockGasAccounting.withdrawals(); fundContract(borrowedAmount); mockGasAccounting.setLock(executionEnvironment, 0, uint8(ExecutionPhase.PostOps)); @@ -471,7 +466,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { mockGasAccounting.borrow(borrowedAmount); assertEq(executionEnvironment.balance, 0, "Execution environment balance should remain zero"); - assertEq(withdrawalsBefore, mockGasAccounting.getWithdrawals(), "Withdrawals should remain unchanged"); + assertEq(withdrawalsBefore, mockGasAccounting.withdrawals(), "Withdrawals should remain unchanged"); } function test_multipleBorrows() public { @@ -535,7 +530,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { "Final contract balance should be initial balance minus total borrowed amount" ); assertEq( - totalBorrowAmount, mockGasAccounting.getWithdrawals(), "Withdrawals should equal total borrowed amount" + totalBorrowAmount, mockGasAccounting.withdrawals(), "Withdrawals should equal total borrowed amount" ); } @@ -667,7 +662,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { vm.prank(executionEnvironment); mockGasAccounting.contribute{ value: 10 ether }(); - assertEq(mockGasAccounting.getClaims(), 10 ether, "Claims should be set to 10 ether"); + assertEq(mockGasAccounting.claims(), 10 ether, "Claims should be set to 10 ether"); assertEq(address(mockGasAccounting).balance, 10 ether, "mockGasAccounting should have 10 ether"); } @@ -741,7 +736,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { assertEq(currentSolver, solverOneEOA, "Current solver should match execution environment"); // Verify that deposits did not increase - assertEq(mockGasAccounting.getDeposits(), initialClaims, "Deposits should remain unchanged"); + assertEq(mockGasAccounting.deposits(), initialClaims, "Deposits should remain unchanged"); } function test_reconcileWithETH() public { @@ -768,7 +763,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { assertEq(currentSolver, solverOneEOA, "Current solver should match execution environment"); // Verify that deposits increased by the reconciled amount - assertEq(mockGasAccounting.getDeposits(), initialClaims, "Deposits should match the amount sent as msg.value"); + assertEq(mockGasAccounting.deposits(), initialClaims, "Deposits should match the amount sent as msg.value"); } function test_assign_zeroAmount() public { @@ -790,7 +785,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { // Get initial values uint256 bondedTotalSupplyBefore = mockGasAccounting.bondedTotalSupply(); - uint256 depositsBefore = mockGasAccounting.getDeposits(); + uint256 depositsBefore = mockGasAccounting.deposits(); uint256 deficit = mockGasAccounting.assign(solverOp.from, assignedAmount, assignedAmount, true); assertEq(deficit, 0, "Deficit should be 0"); @@ -799,7 +794,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { assertEq(lastAccessedBlock, uint32(SafeBlockNumber.get())); uint256 bondedTotalSupplyAfter = mockGasAccounting.bondedTotalSupply(); - uint256 depositsAfter = mockGasAccounting.getDeposits(); + uint256 depositsAfter = mockGasAccounting.deposits(); assertEq(bondedTotalSupplyAfter, bondedTotalSupplyBefore - assignedAmount); assertEq(depositsAfter, depositsBefore + assignedAmount); @@ -815,7 +810,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { mockGasAccounting.increaseBondedBalance(solverOp.from, bondedAmount); // Set bonded balance to 500 uint256 bondedTotalSupplyBefore = mockGasAccounting.bondedTotalSupply(); - uint256 depositsBefore = mockGasAccounting.getDeposits(); + uint256 depositsBefore = mockGasAccounting.deposits(); // Call the assign function and capture the deficit uint256 deficit = mockGasAccounting.assign(solverOp.from, assignedAmount, assignedAmount, true); @@ -831,7 +826,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { bondedTotalSupplyBefore - assignedAmount, "Bonded total supply mismatch" ); - assertEq(mockGasAccounting.getDeposits(), depositsBefore + assignedAmount, "Deposits mismatch"); + assertEq(mockGasAccounting.deposits(), depositsBefore + assignedAmount, "Deposits mismatch"); // Retrieve and check the updated balances (uint112 bonded, uint112 unbonding) = mockGasAccounting._balanceOf(solverOp.from); @@ -849,13 +844,13 @@ contract GasAccountingTest is AtlasConstants, BaseTest { mockGasAccounting.increaseBondedBalance(solverOp.from, bondedAmount); uint256 bondedTotalSupplyBefore = mockGasAccounting.bondedTotalSupply(); - uint256 depositsBefore = mockGasAccounting.getDeposits(); + uint256 depositsBefore = mockGasAccounting.deposits(); uint256 deficit = mockGasAccounting.assign(solverOp.from, assignedAmount, assignedAmount, true); assertEq(deficit, assignedAmount - (unbondingAmount + bondedAmount)); (, uint32 lastAccessedBlock,,,) = mockGasAccounting.accessData(solverOp.from); assertEq(lastAccessedBlock, uint32(SafeBlockNumber.get())); assertEq(mockGasAccounting.bondedTotalSupply(), bondedTotalSupplyBefore - (unbondingAmount + bondedAmount)); - assertEq(mockGasAccounting.getDeposits(), depositsBefore + (unbondingAmount + bondedAmount)); + assertEq(mockGasAccounting.deposits(), depositsBefore + (unbondingAmount + bondedAmount)); (uint112 bonded, uint112 unbonding) = mockGasAccounting._balanceOf(solverOp.from); assertEq(unbonding, 0); assertEq(bonded, 0); @@ -918,14 +913,14 @@ contract GasAccountingTest is AtlasConstants, BaseTest { mockGasAccounting.increaseBondedBalance(solverOp.from, bondedAmount); uint256 bondedTotalSupplyBefore = mockGasAccounting.bondedTotalSupply(); - uint256 depositsBefore = mockGasAccounting.getDeposits(); + uint256 depositsBefore = mockGasAccounting.deposits(); (uint112 unbondingBefore,) = mockGasAccounting._balanceOf(solverOp.from); vm.expectRevert(AtlasErrors.ValueTooLarge.selector); mockGasAccounting.assign(solverOp.from, assignedAmount, assignedAmount, true); // Check assign reverted with overflow, and accounting values did not change assertEq(mockGasAccounting.bondedTotalSupply(), bondedTotalSupplyBefore); - assertEq(mockGasAccounting.getDeposits(), depositsBefore); + assertEq(mockGasAccounting.deposits(), depositsBefore); (uint112 unbonding,) = mockGasAccounting._balanceOf(solverOp.from); assertEq(unbonding, unbondingBefore); } @@ -935,7 +930,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { uint256 lastAccessedBlock; uint256 bondedTotalSupplyBefore = mockGasAccounting.bondedTotalSupply(); - uint256 withdrawalsBefore = mockGasAccounting.getWithdrawals(); + uint256 withdrawalsBefore = mockGasAccounting.withdrawals(); (uint112 bondedBefore,,,,) = mockGasAccounting.accessData(solverOp.from); (, lastAccessedBlock,,,) = mockGasAccounting.accessData(solverOp.from); assertEq(lastAccessedBlock, 0); @@ -948,7 +943,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { assertEq(lastAccessedBlock, uint32(SafeBlockNumber.get())); assertEq(mockGasAccounting.bondedTotalSupply(), bondedTotalSupplyBefore + creditedAmount); assertEq(bondedAfter, bondedBefore + uint112(creditedAmount)); - assertEq(mockGasAccounting.getWithdrawals(), withdrawalsBefore + creditedAmount); + assertEq(mockGasAccounting.withdrawals(), withdrawalsBefore + creditedAmount); // Testing uint112 boundary values for casting from uint256 to uint112 in _credit() uint256 overflowAmount = uint256(type(uint112).max) + 1; @@ -960,7 +955,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { // Setup solverOp.data = ""; uint256 gasWaterMark = gasleft() + 5000; - uint256 initialWriteoffs = mockGasAccounting.getWriteoffs(); + uint256 initialWriteoffs = mockGasAccounting.writeoffs(); // Simulate solver not responsible for failure uint256 result = EscrowBits._NO_REFUND; @@ -974,10 +969,10 @@ contract GasAccountingTest is AtlasConstants, BaseTest { (gasWaterMark + mockGasAccounting.getSolverBaseGasUsed() - gasleft()) * tx.gasprice + gasUsedOffset; mockGasAccounting.handleSolverAccounting(solverOp, gasWaterMark, result, false); - uint256 expectedWriteoffs = initialWriteoffs + AccountingMath.withAtlasAndBundlerSurcharges(gasUsed); + uint256 expectedWriteoffs = initialWriteoffs + AccountingMath.withSurcharges(gasUsed, DEFAULT_ATLAS_SURCHARGE_RATE, DEFAULT_BUNDLER_SURCHARGE_RATE); // Verify writeoffs have increased assertApproxEqRel( - mockGasAccounting.getWriteoffs(), + mockGasAccounting.writeoffs(), expectedWriteoffs, 1e15, // 0.1% margin for error "Writeoffs should be approximately equal to expected value" @@ -1031,15 +1026,6 @@ contract GasAccountingTest is AtlasConstants, BaseTest { assertEq(unbonding, unbondingBefore); } - function test_settle_withFailedsolver_reverts() public { - // Setup context with initial claims and deposits - Context memory ctx = setupContext(1 ether, 1 ether, 4000 ether, 1000 ether, false); - - // Expect a revert due to insufficient total balance for a failed solver - vm.expectRevert(); - mockGasAccounting.settle(ctx); - } - function test_settle_with_deposits() public { Context memory ctx = setupContext(1 ether, 0.5 ether, 4000 ether, 1000 ether, true); // Check initial balances @@ -1055,7 +1041,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { (uint256 claimsPaidToBundler, uint256 netGasSurcharge) = mockGasAccounting.settle(ctx); // Check final balances and perform assertions - uint256 finalClaims = mockGasAccounting.getClaims(); + uint256 finalClaims = mockGasAccounting.claims(); uint256 finalBonded = mockGasAccounting.balanceOfBonded(solverOneEOA); uint256 finalUnbonding = mockGasAccounting.balanceOfUnbonding(solverOneEOA); { @@ -1101,7 +1087,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { assertTrue(claimsPaidToBundler > 0, "Claims paid to bundler should be non-zero"); assertTrue(netGasSurcharge > 0, "Net gas surcharge should be non-zero"); assertLe( - mockGasAccounting.getClaims(), + mockGasAccounting.claims(), 3 ether, "Final claims should be less than or equal to initial claims plus deposits" ); @@ -1111,6 +1097,8 @@ contract GasAccountingTest is AtlasConstants, BaseTest { IL2GasCalculator gasCalculator = new MockGasCalculator(); MockGasAccounting mockL2GasAccounting = new MockGasAccounting( DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, address(atlasVerification), address(simulator), deployer, diff --git a/test/MainTest.t.sol b/test/MainTest.t.sol index 0b9716287..788b8ab9b 100644 --- a/test/MainTest.t.sol +++ b/test/MainTest.t.sol @@ -1,28 +1,28 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; +import { IExecutionEnvironment } from "../src/contracts/interfaces/IExecutionEnvironment.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { Mimic } from "src/contracts/common/Mimic.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { Mimic } from "../src/contracts/common/Mimic.sol"; -import { V2DAppControl } from "src/contracts/examples/v2-example/V2DAppControl.sol"; +import { V2DAppControl } from "../src/contracts/examples/v2-example/V2DAppControl.sol"; -import { Solver } from "src/contracts/solver/src/TestSolver.sol"; +import { Solver } from "../src/contracts/solver/src/TestSolver.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import "../src/contracts/types/UserOperation.sol"; +import "../src/contracts/types/SolverOperation.sol"; +import "../src/contracts/types/EscrowTypes.sol"; +import "../src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; import { V2Helper } from "./V2Helper.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; import "forge-std/Test.sol"; diff --git a/test/Mimic.t.sol b/test/Mimic.t.sol index fcb1ad877..c676dc6a7 100644 --- a/test/Mimic.t.sol +++ b/test/Mimic.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { Mimic } from "src/contracts/common/Mimic.sol"; +import { Mimic } from "../src/contracts/common/Mimic.sol"; contract MimicTest is Test { function testMimicDelegatecall() public { diff --git a/test/NonceManager.t.sol b/test/NonceManager.t.sol index 07f2d6974..76b60b175 100644 --- a/test/NonceManager.t.sol +++ b/test/NonceManager.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { NonceManager } from "src/contracts/atlas/NonceManager.sol"; -import { DAppConfig, CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { DAppOperation } from "src/contracts/types/DAppOperation.sol"; -import { ValidCallsResult } from "src/contracts/types/ValidCalls.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; +import { NonceManager } from "../src/contracts/atlas/NonceManager.sol"; +import { DAppConfig, CallConfig } from "../src/contracts/types/ConfigTypes.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { DAppOperation } from "../src/contracts/types/DAppOperation.sol"; +import { ValidCallsResult } from "../src/contracts/types/ValidCalls.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; import { AtlasVerificationBase } from "./AtlasVerification.t.sol"; contract MockNonceManager is NonceManager { diff --git a/test/OEV.t.sol b/test/OEV.t.sol index 58a57fdc2..267d966e4 100644 --- a/test/OEV.t.sol +++ b/test/OEV.t.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; -import { BaseTest } from "test/base/BaseTest.t.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; +import { BaseTest } from "./base/BaseTest.t.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; import { UserOperationBuilder } from "test/base/builders/UserOperationBuilder.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { DAppConfig } from "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; -import { ChainlinkDAppControl, Oracle, Role } from "src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; -import { ChainlinkAtlasWrapper } from "src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; -import { AggregatorV2V3Interface } from "src/contracts/examples/oev-example/IChainlinkAtlasWrapper.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { ChainlinkDAppControl, Oracle, Role } from "../src/contracts/examples/oev-example/ChainlinkDAppControl.sol"; +import { ChainlinkAtlasWrapper } from "../src/contracts/examples/oev-example/ChainlinkAtlasWrapper.sol"; +import { AggregatorV2V3Interface } from "../src/contracts/examples/oev-example/IChainlinkAtlasWrapper.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; // Using this Chainlink update to ETHUSD feed as an example: diff --git a/test/OEValt.t.sol b/test/OEValt.t.sol index 65f418191..a836e5c1d 100644 --- a/test/OEValt.t.sol +++ b/test/OEValt.t.sol @@ -1,23 +1,23 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; -import { BaseTest } from "test/base/BaseTest.t.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; +import { BaseTest } from "./base/BaseTest.t.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; import { UserOperationBuilder } from "test/base/builders/UserOperationBuilder.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { DAppConfig } from "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; -import { ChainlinkDAppControl, Oracle, Role } from "src/contracts/examples/oev-example/ChainlinkDAppControlAlt.sol"; -import {ChainlinkAtlasWrapper, IChainlinkFeed } from "src/contracts/examples/oev-example/ChainlinkAtlasWrapperAlt.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { ChainlinkDAppControl, Oracle, Role } from "../src/contracts/examples/oev-example/ChainlinkDAppControlAlt.sol"; +import {ChainlinkAtlasWrapper, IChainlinkFeed } from "../src/contracts/examples/oev-example/ChainlinkAtlasWrapperAlt.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; // Using this Chainlink update to ETHUSD feed as an example: diff --git a/test/Permit69.t.sol b/test/Permit69.t.sol index b5b47f4c8..e88227443 100644 --- a/test/Permit69.t.sol +++ b/test/Permit69.t.sol @@ -1,28 +1,28 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; import "./base/TestUtils.sol"; -import { Permit69 } from "src/contracts/atlas/Permit69.sol"; -import { Mimic } from "src/contracts/common/Mimic.sol"; +import { Permit69 } from "../src/contracts/atlas/Permit69.sol"; +import { Mimic } from "../src/contracts/common/Mimic.sol"; +import { FactoryLib } from "../src/contracts/atlas/FactoryLib.sol"; -import { SAFE_USER_TRANSFER, SAFE_DAPP_TRANSFER } from "src/contracts/atlas/Permit69.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import { SAFE_USER_TRANSFER, SAFE_DAPP_TRANSFER } from "../src/contracts/atlas/Permit69.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; +import { ExecutionEnvironment } from "../src/contracts/common/ExecutionEnvironment.sol"; -import { Atlas } from "src/contracts/atlas/Atlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; +import { Atlas } from "../src/contracts/atlas/Atlas.sol"; +import { AtlasVerification } from "../src/contracts/atlas/AtlasVerification.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import "../src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; contract Permit69Test is BaseTest { - Context ctx; address mockUser; @@ -36,25 +36,31 @@ contract Permit69Test is BaseTest { BaseTest.setUp(); mockUser = address(0x13371337); - address deployer = address(333); - address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 0); - address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 1); - address expectedFactoryAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); - bytes32 salt = keccak256(abi.encodePacked(block.chainid, expectedFactoryAddr)); - ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment{ salt: salt }(expectedFactoryAddr); - + + address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); + address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 3); + vm.startPrank(deployer); + ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment(expectedAtlasAddr); + FactoryLib factoryLib = new FactoryLib(address(execEnvTemplate)); + mockAtlas = new MockAtlasForPermit69Tests({ - _escrowDuration: 64, - _verification: expectedAtlasVerificationAddr, - _simulator: address(0), - _executionTemplate: address(execEnvTemplate), + escrowDuration: 64, + atlasSurchargeRate: DEFAULT_ATLAS_SURCHARGE_RATE, + bundlerSurchargeRate: DEFAULT_BUNDLER_SURCHARGE_RATE, + verification: expectedAtlasVerificationAddr, + simulator: address(0), + factoryLib: address(factoryLib), _surchargeRecipient: deployer, - _l2GasCalculator: address(0) + l2GasCalculator: address(0) }); + vm.stopPrank(); + + console.log("Mock Atlas address: ", address(mockAtlas)); + console.log("Predicted atlas address: ", expectedAtlasAddr); + assertEq(address(mockAtlas), expectedAtlasAddr, "Atlas address mismatch"); - vm.stopPrank(); mockDAppControl = address(0x123321); mockCallConfig = 0; @@ -97,9 +103,7 @@ contract Permit69Test is BaseTest { vm.prank(solverOneEOA); vm.expectRevert(AtlasErrors.InvalidEnvironment.selector); - mockAtlas.transferUserERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferUserERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); } function testTransferUserERC20RevertsIfLockStateNotValid() public { @@ -115,27 +119,21 @@ contract Permit69Test is BaseTest { // Uninitialized vm.expectRevert(AtlasErrors.InvalidLockState.selector); - mockAtlas.transferUserERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferUserERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); // AllocateValue phase = ExecutionPhase.AllocateValue; mockAtlas.setContext(ctx); mockAtlas.setPhase(phase); vm.expectRevert(AtlasErrors.InvalidLockState.selector); - mockAtlas.transferUserERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferUserERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); // Releasing phase = ExecutionPhase.Uninitialized; mockAtlas.setContext(ctx); mockAtlas.setPhase(phase); vm.expectRevert(AtlasErrors.InvalidLockState.selector); - mockAtlas.transferUserERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferUserERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); vm.stopPrank(); } @@ -157,9 +155,7 @@ contract Permit69Test is BaseTest { WETH.approve(address(mockAtlas), wethTransferred); vm.prank(mockExecutionEnvAddress); - mockAtlas.transferUserERC20( - WETH_ADDRESS, solverOneEOA, wethTransferred, mockUser, mockDAppControl - ); + mockAtlas.transferUserERC20(WETH_ADDRESS, solverOneEOA, wethTransferred, mockUser, mockDAppControl); assertEq(WETH.balanceOf(mockUser), userWethBefore - wethTransferred, "User did not lose WETH"); assertEq(WETH.balanceOf(solverOneEOA), solverWethBefore + wethTransferred, "Solver did not gain WETH"); @@ -173,9 +169,7 @@ contract Permit69Test is BaseTest { vm.prank(solverOneEOA); vm.expectRevert(AtlasErrors.InvalidEnvironment.selector); - mockAtlas.transferDAppERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferDAppERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); } function testTransferDAppERC20RevertsIfLockStateNotValid() public { @@ -189,33 +183,25 @@ contract Permit69Test is BaseTest { ExecutionPhase phase = ExecutionPhase.Uninitialized; mockAtlas.setPhase(phase); vm.expectRevert(AtlasErrors.InvalidLockState.selector); - mockAtlas.transferDAppERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferDAppERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); // UserOperation phase = ExecutionPhase.UserOperation; mockAtlas.setPhase(phase); vm.expectRevert(AtlasErrors.InvalidLockState.selector); - mockAtlas.transferDAppERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferDAppERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); // SolverOperations phase = ExecutionPhase.SolverOperation; mockAtlas.setPhase(phase); vm.expectRevert(AtlasErrors.InvalidLockState.selector); - mockAtlas.transferDAppERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferDAppERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); // Releasing phase = ExecutionPhase.Uninitialized; mockAtlas.setPhase(phase); vm.expectRevert(AtlasErrors.InvalidLockState.selector); - mockAtlas.transferDAppERC20( - WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl - ); + mockAtlas.transferDAppERC20(WETH_ADDRESS, solverOneEOA, 10e18, mockUser, mockDAppControl); vm.stopPrank(); } @@ -236,9 +222,7 @@ contract Permit69Test is BaseTest { WETH.approve(address(mockAtlas), wethTransferred); vm.prank(mockExecutionEnvAddress); - mockAtlas.transferDAppERC20( - WETH_ADDRESS, solverOneEOA, wethTransferred, mockUser, mockDAppControl - ); + mockAtlas.transferDAppERC20(WETH_ADDRESS, solverOneEOA, wethTransferred, mockUser, mockDAppControl); assertEq(WETH.balanceOf(mockDAppControl), dAppWethBefore - wethTransferred, "DApp did not lose WETH"); assertEq(WETH.balanceOf(solverOneEOA), solverWethBefore + wethTransferred, "Solver did not gain WETH"); @@ -279,7 +263,7 @@ contract Permit69Test is BaseTest { function testConstantValueOfSafeDAppTransfer() public { // FIXME: fix before merging spearbit-reaudit branch vm.skip(true); - + string memory expectedBitMapString = "0000111010100000"; // Safe phases for dApp transfers are PreOps, AllocateValue, and DAppOperation // preOpsPhaseSafe = 0000 0000 0010 0000 @@ -293,8 +277,8 @@ contract Permit69Test is BaseTest { // verificationPhaseSafe = 0000 0100 0000 0000 uint8 verificationPhaseSafe = uint8(ExecutionPhase.PostOps); - uint16 expectedSafeDAppTransferBitMap = - preOpsPhaseSafe | preSolverOpsPhaseSafe | postSolverOpsPhaseSafe | allocateValuePhaseSafe | verificationPhaseSafe; + uint16 expectedSafeDAppTransferBitMap = preOpsPhaseSafe | preSolverOpsPhaseSafe | postSolverOpsPhaseSafe + | allocateValuePhaseSafe | verificationPhaseSafe; assertEq( mockAtlas.getSafeDAppTransfer(), @@ -322,14 +306,25 @@ contract Permit69Test is BaseTest { // Mock Atlas with standard implementations of Permit69's virtual functions contract MockAtlasForPermit69Tests is Atlas { constructor( - uint256 _escrowDuration, - address _verification, - address _simulator, + uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, + address verification, + address simulator, address _surchargeRecipient, - address _l2GasCalculator, - address _executionTemplate + address l2GasCalculator, + address factoryLib ) - Atlas(_escrowDuration, _verification, _simulator, _surchargeRecipient, _l2GasCalculator, _executionTemplate) + Atlas( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + _surchargeRecipient, + l2GasCalculator, + factoryLib + ) { } // Declared in SafetyLocks.sol in the canonical Atlas system @@ -354,10 +349,7 @@ contract MockAtlasForPermit69Tests is Atlas { _environment = _activeEnvironment; } - function setLock( - address _activeEnvironment, - uint32 callConfig - ) public { + function setLock(address _activeEnvironment, uint32 callConfig) public { _setLock({ activeEnvironment: _activeEnvironment, callConfig: callConfig, @@ -376,18 +368,25 @@ contract MockAtlasForPermit69Tests is Atlas { uint32 callConfig ) public - returns (address executionEnvironment) + returns (address executionEnvironment) { return _getOrCreateExecutionEnvironment(user, control, callConfig); } - function verifyUserControlExecutionEnv(address sender, address user, address control, uint32 callConfig) internal view returns (bool) + function verifyUserControlExecutionEnv( + address sender, + address user, + address control, + uint32 callConfig + ) + internal + returns (bool) { return _verifyUserControlExecutionEnv(sender, user, control, callConfig); } // Exposing above overridden function for testing and Permit69 coverage - function verifyCallerIsExecutionEnv(address user, address control, uint32 callConfig) public view returns (bool) { + function verifyCallerIsExecutionEnv(address user, address control, uint32 callConfig) public returns (bool) { if (!_verifyUserControlExecutionEnv(msg.sender, user, control, callConfig)) { revert AtlasErrors.InvalidEnvironment(); } diff --git a/test/SafetyLocks.t.sol b/test/SafetyLocks.t.sol index 5fab4b491..c4d1bd4fc 100644 --- a/test/SafetyLocks.t.sol +++ b/test/SafetyLocks.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { SafetyLocks } from "src/contracts/atlas/SafetyLocks.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import { SafetyLocks } from "../src/contracts/atlas/SafetyLocks.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/LockTypes.sol"; contract MockSafetyLocks is SafetyLocks { - constructor() SafetyLocks(0, address(0), address(0), address(0), address(0)) { } + constructor() SafetyLocks(0, 1000000, 1000000, address(0), address(0), address(0), address(0)) { } function initializeLock( address executionEnvironment, @@ -56,58 +56,58 @@ contract MockSafetyLocks is SafetyLocks { _setLockPhase(newPhase); } - function setClaims(uint256 _claims) external { - _setClaims(_claims); + function setSolverLock(uint256 newSolverLock) public { + t_solverLock = newSolverLock; } - function setWithdrawals(uint256 _withdrawals) external { - _setWithdrawals(_withdrawals); + function setSolverTo(address newSolverTo) public { + t_solverTo = newSolverTo; } - function setDeposits(uint256 _deposits) external { - _setDeposits(_deposits); + function setClaims(uint256 newClaims) public { + t_claims = newClaims; } - function setFees(uint256 _fees) external { - _setFees(_fees); + function setFees(uint256 newFees) public { + t_fees = newFees; } - function setWriteoffs(uint256 _writeoffs) external { - _setWriteoffs(_writeoffs); + function setWriteoffs(uint256 newWriteoffs) public { + t_writeoffs = newWriteoffs; } - function setSolverLock(uint256 newSolverLock) external { - _setSolverLock(newSolverLock); + function setWithdrawals(uint256 newWithdrawals) public { + t_withdrawals = newWithdrawals; } - function setSolverTo(address newSolverTo) external { - _setSolverTo(newSolverTo); + function setDeposits(uint256 newDeposits) public { + t_deposits = newDeposits; } - function solverTo() external view returns (address) { - return _solverTo(); - } + // Transient Var View Functions - // View functions + function claims() external view returns (uint256) { + return t_claims; + } - function getClaims() external view returns (uint256) { - return claims(); + function fees() external view returns (uint256) { + return t_fees; } - function getFees() external view returns (uint256) { - return fees(); + function writeoffs() external view returns (uint256) { + return t_writeoffs; } - function getWriteoffs() external view returns (uint256) { - return writeoffs(); + function withdrawals() external view returns (uint256) { + return t_withdrawals; } - function getWithdrawals() external view returns (uint256) { - return withdrawals(); + function deposits() external view returns (uint256) { + return t_deposits; } - function getDeposits() external view returns (uint256) { - return deposits(); + function solverTo() external view returns (address) { + return t_solverTo; } } @@ -158,7 +158,7 @@ contract SafetyLocksTest is Test { safetyLocks.setClaims(newClaims); - uint256 claims = safetyLocks.getClaims(); + uint256 claims = safetyLocks.claims(); assertEq(claims, newClaims); } @@ -167,7 +167,7 @@ contract SafetyLocksTest is Test { safetyLocks.setWithdrawals(newWithdrawals); - uint256 withdrawals = safetyLocks.getWithdrawals(); + uint256 withdrawals = safetyLocks.withdrawals(); assertEq(withdrawals, newWithdrawals); } @@ -176,7 +176,7 @@ contract SafetyLocksTest is Test { safetyLocks.setDeposits(newDeposits); - uint256 deposits = safetyLocks.getDeposits(); + uint256 deposits = safetyLocks.deposits(); assertEq(deposits, newDeposits); } @@ -185,7 +185,7 @@ contract SafetyLocksTest is Test { safetyLocks.setFees(newFees); - uint256 fees = safetyLocks.getFees(); + uint256 fees = safetyLocks.fees(); assertEq(fees, newFees); } @@ -194,7 +194,7 @@ contract SafetyLocksTest is Test { safetyLocks.setWriteoffs(newWriteoffs); - uint256 writeoffs = safetyLocks.getWriteoffs(); + uint256 writeoffs = safetyLocks.writeoffs(); assertEq(writeoffs, newWriteoffs); } @@ -245,11 +245,11 @@ contract SafetyLocksTest is Test { safetyLocks.setSolverLock(0x456); (address activeEnv, uint32 callConfig, uint8 phase) = safetyLocks.lock(); - uint256 claims = safetyLocks.getClaims(); - uint256 withdrawals = safetyLocks.getWithdrawals(); - uint256 deposits = safetyLocks.getDeposits(); - uint256 fees = safetyLocks.getFees(); - uint256 writeoffs = safetyLocks.getWriteoffs(); + uint256 claims = safetyLocks.claims(); + uint256 withdrawals = safetyLocks.withdrawals(); + uint256 deposits = safetyLocks.deposits(); + uint256 fees = safetyLocks.fees(); + uint256 writeoffs = safetyLocks.writeoffs(); (address solverTo,,) = safetyLocks.solverLockData(); assertEq(safetyLocks.isUnlocked(), false); diff --git a/test/Simulator.t.sol b/test/Simulator.t.sol index 4995bd44a..6485b1f1a 100644 --- a/test/Simulator.t.sol +++ b/test/Simulator.t.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { Result } from "src/contracts/helpers/Simulator.sol"; -import { DAppConfig, CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; -import { ValidCallsResult } from "src/contracts/types/ValidCalls.sol"; -import { SolverOutcome } from "src/contracts/types/EscrowTypes.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; +import { Result } from "../src/contracts/helpers/Simulator.sol"; +import { DAppConfig, CallConfig } from "../src/contracts/types/ConfigTypes.sol"; +import { DAppOperation } from "../src/contracts/types/DAppOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; +import { ValidCallsResult } from "../src/contracts/types/ValidCalls.sol"; +import { SolverOutcome } from "../src/contracts/types/EscrowTypes.sol"; +import { CallVerification } from "../src/contracts/libraries/CallVerification.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; import { UserOperationBuilder } from "./base/builders/UserOperationBuilder.sol"; @@ -23,7 +23,7 @@ import { CallConfigBuilder } from "./helpers/CallConfigBuilder.sol"; import { DummyDAppControlBuilder } from "./helpers/DummyDAppControlBuilder.sol"; import { DummyDAppControl } from "./base/DummyDAppControl.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; contract SimulatorTest is BaseTest { diff --git a/test/Sorter.t.sol b/test/Sorter.t.sol index a2d51dad5..1331ee5f7 100644 --- a/test/Sorter.t.sol +++ b/test/Sorter.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { BaseTest } from "./base/BaseTest.t.sol"; @@ -10,8 +10,8 @@ import { UserOperationBuilder } from "./base/builders/UserOperationBuilder.sol"; import { SolverOperationBuilder } from "./base/builders/SolverOperationBuilder.sol"; import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; +import "../src/contracts/types/UserOperation.sol"; +import "../src/contracts/types/SolverOperation.sol"; contract SorterTest is BaseTest { DummyDAppControl dAppControl; diff --git a/test/Storage.t.sol b/test/Storage.t.sol index 7fa18a324..4c43ec18d 100644 --- a/test/Storage.t.sol +++ b/test/Storage.t.sol @@ -1,19 +1,16 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { Storage } from "src/contracts/atlas/Storage.sol"; -import "src/contracts/types/LockTypes.sol"; - -import { BaseTest } from "test/base/BaseTest.t.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; +import { Storage } from "../src/contracts/atlas/Storage.sol"; +import "../src/contracts/types/LockTypes.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; +import { BaseTest } from "./base/BaseTest.t.sol"; contract StorageTest is BaseTest { using stdStorage for StdStorage; - uint256 constant DEFAULT_ATLAS_SURCHARGE_RATE = 1_000_000; // out of 10_000_000 = 10% - uint256 constant DEFAULT_BUNDLER_SURCHARGE_RATE = 1_000_000; // out of 10_000_000 = 10% uint256 constant DEFAULT_SCALE = 10_000_000; // out of 10_000_000 = 100% uint256 constant DEFAULT_FIXED_GAS_OFFSET = 85_000; @@ -33,7 +30,9 @@ contract StorageTest is BaseTest { assertEq(atlas.decimals(), 18, "decimals set incorrectly"); assertEq(atlas.ATLAS_SURCHARGE_RATE(), DEFAULT_ATLAS_SURCHARGE_RATE, "ATLAS_SURCHARGE_RATE set incorrectly"); - assertEq(atlas.BUNDLER_SURCHARGE_RATE(), DEFAULT_BUNDLER_SURCHARGE_RATE, "BUNDLER_SURCHARGE_RATE set incorrectly"); + assertEq( + atlas.BUNDLER_SURCHARGE_RATE(), DEFAULT_BUNDLER_SURCHARGE_RATE, "BUNDLER_SURCHARGE_RATE set incorrectly" + ); assertEq(atlas.SCALE(), DEFAULT_SCALE, "SCALE set incorrectly"); assertEq(atlas.FIXED_GAS_OFFSET(), DEFAULT_FIXED_GAS_OFFSET, "FIXED_GAS_OFFSET set incorrectly"); } @@ -46,7 +45,7 @@ contract StorageTest is BaseTest { vm.deal(userEOA, depositAmount); vm.prank(userEOA); - atlas.deposit{value: depositAmount}(); + atlas.deposit{ value: depositAmount }(); assertEq(atlas.totalSupply(), startTotalSupply + depositAmount, "totalSupply did not increase correctly"); } @@ -57,14 +56,20 @@ contract StorageTest is BaseTest { vm.deal(userEOA, depositAmount); vm.prank(userEOA); - atlas.depositAndBond{value: depositAmount}(depositAmount); + atlas.depositAndBond{ value: depositAmount }(depositAmount); assertEq(atlas.bondedTotalSupply(), depositAmount, "bondedTotalSupply did not increase correctly"); } function test_storage_view_accessData() public { uint256 depositAmount = 1e18; - (uint256 bonded, uint256 lastAccessedBlock, uint256 auctionWins, uint256 auctionFails, uint256 totalGasValueUsed) = atlas.accessData(userEOA); + ( + uint256 bonded, + uint256 lastAccessedBlock, + uint256 auctionWins, + uint256 auctionFails, + uint256 totalGasValueUsed + ) = atlas.accessData(userEOA); assertEq(bonded, 0, "user bonded should start as 0"); assertEq(lastAccessedBlock, 0, "user lastAccessedBlock should start as 0"); @@ -74,7 +79,7 @@ contract StorageTest is BaseTest { vm.deal(userEOA, depositAmount); vm.prank(userEOA); - atlas.depositAndBond{value: depositAmount}(depositAmount); + atlas.depositAndBond{ value: depositAmount }(depositAmount); (bonded, lastAccessedBlock, auctionWins, auctionFails, totalGasValueUsed) = atlas.accessData(userEOA); @@ -97,7 +102,15 @@ contract StorageTest is BaseTest { } function test_storage_view_solverOpHashes() public { - MockStorage mockStorage = new MockStorage(DEFAULT_ESCROW_DURATION, address(0), address(0), address(0), address(0)); + MockStorage mockStorage = new MockStorage( + DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, + address(0), + address(0), + address(0), + address(0) + ); bytes32 testHash = keccak256(abi.encodePacked("test")); assertEq(mockStorage.solverOpHashes(testHash), false, "solverOpHashes[testHash] not false"); mockStorage.setSolverOpHash(testHash); @@ -105,7 +118,15 @@ contract StorageTest is BaseTest { } function test_storage_view_cumulativeSurcharge() public { - MockStorage mockStorage = new MockStorage(DEFAULT_ESCROW_DURATION, address(0), address(0), address(0), address(0)); + MockStorage mockStorage = new MockStorage( + DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, + address(0), + address(0), + address(0), + address(0) + ); assertEq(mockStorage.cumulativeSurcharge(), 0, "cumulativeSurcharge not 0"); mockStorage.setCumulativeSurcharge(100); assertEq(mockStorage.cumulativeSurcharge(), 100, "cumulativeSurcharge not 100"); @@ -158,7 +179,15 @@ contract StorageTest is BaseTest { function test_storage_transient_solverLockData() public { // MockStorage just used here to access AtlasConstants - MockStorage mockStorage = new MockStorage(DEFAULT_ESCROW_DURATION, address(0), address(0), address(0), address(0)); + MockStorage mockStorage = new MockStorage( + DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, + address(0), + address(0), + address(0), + address(0) + ); (address currentSolver, bool calledBack, bool fulfilled) = atlas.solverLockData(); assertEq(currentSolver, address(0), "currentSolver should start at 0"); @@ -181,7 +210,8 @@ contract StorageTest is BaseTest { assertEq(calledBack, true, "calledBack should still be true"); assertEq(fulfilled, true, "fulfilled should be true"); - testSolverLock = mockStorage.SOLVER_CALLED_BACK_MASK() | mockStorage.SOLVER_FULFILLED_MASK() | uint256(uint160(userEOA)); + testSolverLock = + mockStorage.SOLVER_CALLED_BACK_MASK() | mockStorage.SOLVER_FULFILLED_MASK() | uint256(uint160(userEOA)); atlas.setSolverLock(testSolverLock); (currentSolver, calledBack, fulfilled) = atlas.solverLockData(); @@ -198,57 +228,65 @@ contract StorageTest is BaseTest { } function test_storage_transient_claims() public { - assertEq(atlas.getClaims(), 0, "claims should start at 0"); + assertEq(atlas.claims(), 0, "claims should start at 0"); atlas.setClaims(100); - assertEq(atlas.getClaims(), 100, "claims should be 100"); + assertEq(atlas.claims(), 100, "claims should be 100"); atlas.clearTransientStorage(); - assertEq(atlas.getClaims(), 0, "claims should be 0 again"); + assertEq(atlas.claims(), 0, "claims should be 0 again"); } function test_storage_transient_fees() public { - assertEq(atlas.getFees(), 0, "fees should start at 0"); + assertEq(atlas.fees(), 0, "fees should start at 0"); atlas.setFees(100); - assertEq(atlas.getFees(), 100, "fees should be 100"); + assertEq(atlas.fees(), 100, "fees should be 100"); atlas.clearTransientStorage(); - assertEq(atlas.getFees(), 0, "fees should be 0 again"); + assertEq(atlas.fees(), 0, "fees should be 0 again"); } function test_storage_transient_writeoffs() public { - assertEq(atlas.getWriteoffs(), 0, "writeoffs should start at 0"); + assertEq(atlas.writeoffs(), 0, "writeoffs should start at 0"); atlas.setWriteoffs(100); - assertEq(atlas.getWriteoffs(), 100, "writeoffs should be 100"); + assertEq(atlas.writeoffs(), 100, "writeoffs should be 100"); atlas.clearTransientStorage(); - assertEq(atlas.getWriteoffs(), 0, "writeoffs should be 0 again"); + assertEq(atlas.writeoffs(), 0, "writeoffs should be 0 again"); } function test_storage_transient_withdrawals() public { - assertEq(atlas.getWithdrawals(), 0, "withdrawals should start at 0"); + assertEq(atlas.withdrawals(), 0, "withdrawals should start at 0"); atlas.setWithdrawals(100); - assertEq(atlas.getWithdrawals(), 100, "withdrawals should be 100"); + assertEq(atlas.withdrawals(), 100, "withdrawals should be 100"); atlas.clearTransientStorage(); - assertEq(atlas.getWithdrawals(), 0, "withdrawals should be 0 again"); + assertEq(atlas.withdrawals(), 0, "withdrawals should be 0 again"); } function test_storage_transient_deposits() public { - assertEq(atlas.getDeposits(), 0, "deposits should start at 0"); + assertEq(atlas.deposits(), 0, "deposits should start at 0"); atlas.setDeposits(100); - assertEq(atlas.getDeposits(), 100, "deposits should be 100"); + assertEq(atlas.deposits(), 100, "deposits should be 100"); atlas.clearTransientStorage(); - assertEq(atlas.getDeposits(), 0, "deposits should be 0 again"); + assertEq(atlas.deposits(), 0, "deposits should be 0 again"); } function test_storage_transient_solverTo() public { - MockStorage mockStorage = new MockStorage(DEFAULT_ESCROW_DURATION, address(0), address(0), address(0), address(0)); + MockStorage mockStorage = new MockStorage( + DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, + address(0), + address(0), + address(0), + address(0) + ); assertEq(mockStorage.solverTo(), address(0), "solverTo should start at 0"); mockStorage.setSolverTo(userEOA); @@ -259,7 +297,15 @@ contract StorageTest is BaseTest { } function test_storage_transient_activeEnvironment() public { - MockStorage mockStorage = new MockStorage(DEFAULT_ESCROW_DURATION, address(0), address(0), address(0), address(0)); + MockStorage mockStorage = new MockStorage( + DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, + address(0), + address(0), + address(0), + address(0) + ); assertEq(mockStorage.activeEnvironment(), address(0), "activeEnvironment should start at 0"); mockStorage.setLock(address(1), 0, 0); @@ -270,7 +316,15 @@ contract StorageTest is BaseTest { } function test_storage_transient_activeCallConfig() public { - MockStorage mockStorage = new MockStorage(DEFAULT_ESCROW_DURATION, address(0), address(0), address(0), address(0)); + MockStorage mockStorage = new MockStorage( + DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, + address(0), + address(0), + address(0), + address(0) + ); assertEq(mockStorage.activeCallConfig(), 0, "activeCallConfig should start at 0"); mockStorage.setLock(address(0), 1, 0); @@ -281,7 +335,15 @@ contract StorageTest is BaseTest { } function test_storage_transient_phase() public { - MockStorage mockStorage = new MockStorage(DEFAULT_ESCROW_DURATION, address(0), address(0), address(0), address(0)); + MockStorage mockStorage = new MockStorage( + DEFAULT_ESCROW_DURATION, + DEFAULT_ATLAS_SURCHARGE_RATE, + DEFAULT_BUNDLER_SURCHARGE_RATE, + address(0), + address(0), + address(0), + address(0) + ); assertEq(mockStorage.phase(), 0, "phase should start at 0"); mockStorage.setLock(address(0), 0, 1); @@ -294,19 +356,28 @@ contract StorageTest is BaseTest { // To test solverOpHashes() and cumulativeSurcharge() view function contract MockStorage is Storage { - // For solverLockData test uint256 public constant SOLVER_CALLED_BACK_MASK = _SOLVER_CALLED_BACK_MASK; uint256 public constant SOLVER_FULFILLED_MASK = _SOLVER_FULFILLED_MASK; constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator ) - Storage(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator) + Storage( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator + ) { } function setSolverOpHash(bytes32 opHash) public { @@ -320,11 +391,11 @@ contract MockStorage is Storage { // For internal view functions without external versions function solverTo() public view returns (address) { - return _solverTo(); + return t_solverTo; } function setSolverTo(address newSolverTo) public { - _setSolverTo(newSolverTo); + t_solverTo = newSolverTo; } function activeEnvironment() public view returns (address) { @@ -347,34 +418,13 @@ contract MockStorage is Storage { // To clear all transient storage vars function clearTransientStorage() public { _setLock(address(0), 0, 0); - _setSolverLock(0); - _setSolverTo(address(0)); - _setClaims(0); - _setFees(0); - _setWriteoffs(0); - _setWithdrawals(0); - _setDeposits(0); - } - - // View functions - - function getClaims() external view returns (uint256) { - return claims(); - } - - function getFees() external view returns (uint256) { - return fees(); + t_solverLock = 0; + t_solverTo = address(0); + t_claims = 0; + t_fees = 0; + t_writeoffs = 0; + t_withdrawals = 0; + t_deposits = 0; + t_solverSurcharge = 0; } - - function getWriteoffs() external view returns (uint256) { - return writeoffs(); - } - - function getWithdrawals() external view returns (uint256) { - return withdrawals(); - } - - function getDeposits() external view returns (uint256) { - return deposits(); - } -} \ No newline at end of file +} diff --git a/test/Surcharge.t.sol b/test/Surcharge.t.sol index 2c1516b13..7ee7b2749 100644 --- a/test/Surcharge.t.sol +++ b/test/Surcharge.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { AtlasEvents } from "src/contracts/types/AtlasEvents.sol"; -import { AtlasErrors } from "src/contracts/types/AtlasErrors.sol"; +import { AtlasEvents } from "../src/contracts/types/AtlasEvents.sol"; +import { AtlasErrors } from "../src/contracts/types/AtlasErrors.sol"; contract SurchargeTest is BaseTest { using stdStorage for StdStorage; diff --git a/test/SwapIntent.t.sol b/test/SwapIntent.t.sol index 09ccef145..5ae6b8ce2 100644 --- a/test/SwapIntent.t.sol +++ b/test/SwapIntent.t.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { DAppConfig } from "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; import { SwapIntentDAppControl, SwapIntent, Condition -} from "src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +} from "../src/contracts/examples/intents-example/SwapIntentDAppControl.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; interface IUniV2Router02 { function swapExactTokensForTokens( diff --git a/test/SwapIntentInvertBid.t.sol b/test/SwapIntentInvertBid.t.sol index 4d8e8abe3..4af3f86fd 100644 --- a/test/SwapIntentInvertBid.t.sol +++ b/test/SwapIntentInvertBid.t.sol @@ -1,20 +1,20 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import { SwapIntent, SwapIntentInvertBidDAppControl } from "src/contracts/examples/intents-example/SwapIntentInvertBidDAppControl.sol"; -import { SolverBaseInvertBid } from "src/contracts/solver/SolverBaseInvertBid.sol"; -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/DAppOperation.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { DAppConfig } from "../src/contracts/types/ConfigTypes.sol"; +import { SwapIntent, SwapIntentInvertBidDAppControl } from "../src/contracts/examples/intents-example/SwapIntentInvertBidDAppControl.sol"; +import { SolverBaseInvertBid } from "../src/contracts/solver/SolverBaseInvertBid.sol"; +import { DAppControl } from "../src/contracts/dapp/DAppControl.sol"; +import { CallConfig } from "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/DAppOperation.sol"; contract SwapIntentTest is BaseTest { Sig public sig; diff --git a/test/TrebleSwap.t.sol b/test/TrebleSwap.t.sol index 9ac734205..e118e588b 100644 --- a/test/TrebleSwap.t.sol +++ b/test/TrebleSwap.t.sol @@ -1,20 +1,20 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import { DAppOperation } from "src/contracts/types/DAppOperation.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { DAppConfig } from "../src/contracts/types/ConfigTypes.sol"; +import { DAppOperation } from "../src/contracts/types/DAppOperation.sol"; +import { CallVerification } from "../src/contracts/libraries/CallVerification.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; import { BaseTest } from "./base/BaseTest.t.sol"; -import { TrebleSwapDAppControl } from "src/contracts/examples/trebleswap/TrebleSwapDAppControl.sol"; +import { TrebleSwapDAppControl } from "../src/contracts/examples/trebleswap/TrebleSwapDAppControl.sol"; contract TrebleSwapTest is BaseTest { struct SwapTokenInfo { @@ -52,7 +52,7 @@ contract TrebleSwapTest is BaseTest { address BRETT = 0x532f27101965dd16442E59d40670FaF5eBB142E4; address TREB; // will be set to value in DAppControl in setUp - uint256 ERR_MARGIN = 0.18e18; // 18% error margin + uint256 ERR_MARGIN = 0.22e18; // 22% error margin uint256 bundlerGasEth = 1e16; TrebleSwapDAppControl trebleSwapControl; @@ -117,7 +117,7 @@ contract TrebleSwapTest is BaseTest { _doMetacallAndChecks({ winningSolver: address(0) }); } - function testTrebleSwap_Metacall_Erc20ToErc20_OneSolver() public { + function testTrebleSwap_Metacall_Erc20ToErc20_OneSolver_GasCheck() public { // Tx: https://basescan.org/tx/0x0ef4a9c24bbede2b39e12f5e5417733fa8183f372e41ee099c2c7523064c1b55 // Swaps 197.2 USDC for at least 198,080,836.0295 WUF @@ -199,7 +199,7 @@ contract TrebleSwapTest is BaseTest { _doMetacallAndChecks({ winningSolver: address(0) }); } - function testTrebleSwap_Metacall_EthToErc20_OneSolver() public { + function testTrebleSwap_Metacall_EthToErc20_OneSolver_GasCheck() public { // Tx: https://basescan.org/tx/0xe138def4155bea056936038b9374546a366828ab8bf1233056f9e2fe4c6af999 // Swaps 0.123011147164483512 ETH for at least 307.405807527716546728 DAI @@ -288,9 +288,7 @@ contract TrebleSwapTest is BaseTest { beforeVars.solverTrebBalance = _balanceOf(address(TREB), winningSolver); beforeVars.burnAddressTrebBalance = _balanceOf(address(TREB), BURN); beforeVars.atlasGasSurcharge = atlas.cumulativeSurcharge(); - uint256 msgValue = (args.nativeInput ? swapInfo.inputAmount : 0) + bundlerGasEth; - if (args.nativeInput) beforeVars.userInputTokenBalance -= bundlerGasEth; - if (args.nativeOutput) beforeVars.userOutputTokenBalance -= bundlerGasEth; + uint256 msgValue = args.nativeInput ? swapInfo.inputAmount : 0; uint256 txGasUsed; uint256 estAtlasGasSurcharge = gasleft(); // Reused below during calculations @@ -303,16 +301,34 @@ contract TrebleSwapTest is BaseTest { txGasUsed = estAtlasGasSurcharge - gasleft(); estAtlasGasSurcharge = txGasUsed * tx.gasprice * atlas.ATLAS_SURCHARGE_RATE() / atlas.SCALE(); + // For benchmarking + console.log("Metacall gas cost: ", txGasUsed); + // Check Atlas auctionWon return value assertEq(auctionWon, auctionWonExpected, "auctionWon not as expected"); + // Check msg.value is 0 unless sending ETH as the input token to be swapped + if (!args.nativeInput) assertEq(msgValue, 0, "msgValue should have been 0"); + // Check Atlas gas surcharge change - assertApproxEqRel( - atlas.cumulativeSurcharge() - beforeVars.atlasGasSurcharge, - estAtlasGasSurcharge, - ERR_MARGIN, - "Atlas gas surcharge not within estimated range" - ); + if (args.solverOps.length > 0 && auctionWonExpected) { + assertApproxEqRel( + atlas.cumulativeSurcharge() - beforeVars.atlasGasSurcharge, + estAtlasGasSurcharge, + ERR_MARGIN, + "Atlas gas surcharge not within estimated range" + ); + } else if (args.solverOps.length == 0) { + // No surcharge taken if no solvers. + assertEq( + atlas.cumulativeSurcharge(), + beforeVars.atlasGasSurcharge, + "Atlas gas surcharge changed when zero solvers" + ); + } else { + // If solver failed (solver's fault), surcharge still taken, but only on failing solverOp portion. Difficult + // to estimate what that would be so skip this check in that 1 test case. + } // Check user input token change if (args.nativeInput && auctionWonExpected) { diff --git a/test/V2Helper.sol b/test/V2Helper.sol index 8b8c77672..6ab5c4a1c 100644 --- a/test/V2Helper.sol +++ b/test/V2Helper.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; -import { IUniswapV2Pair } from "src/contracts/examples/v2-example/interfaces/IUniswapV2Pair.sol"; +import { IUniswapV2Pair } from "../src/contracts/examples/v2-example/interfaces/IUniswapV2Pair.sol"; -import { BlindBackrun } from "src/contracts/solver/src/BlindBackrun/BlindBackrun.sol"; +import { BlindBackrun } from "../src/contracts/solver/src/BlindBackrun/BlindBackrun.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "src/contracts/types/LockTypes.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; +import "../src/contracts/types/SolverOperation.sol"; +import "../src/contracts/types/UserOperation.sol"; +import "../src/contracts/types/ConfigTypes.sol"; +import "../src/contracts/types/EscrowTypes.sol"; +import "../src/contracts/types/LockTypes.sol"; +import "../src/contracts/types/ConfigTypes.sol"; import "forge-std/Test.sol"; @@ -60,12 +60,6 @@ contract V2Helper is Test, TxBuilder { { (uint256 token0Balance, uint256 token1Balance) = _getTradeAmtAndDirection(firstPool, secondPool, tokenIn); - console.log("-"); - console.log("sell token", tokenIn); - console.log("token0 in ", token0Balance); - console.log("token1 in ", token1Balance); - console.log("-"); - return TxBuilder.buildUserOperation( from, firstPool, diff --git a/test/V2RewardDAppControl.t.sol b/test/V2RewardDAppControl.t.sol index 4647e944b..3de5660ef 100644 --- a/test/V2RewardDAppControl.t.sol +++ b/test/V2RewardDAppControl.t.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; -import { BaseTest } from "test/base/BaseTest.t.sol"; -import { TxBuilder } from "src/contracts/helpers/TxBuilder.sol"; -import { UserOperationBuilder } from "test/base/builders/UserOperationBuilder.sol"; +import { BaseTest } from "./base/BaseTest.t.sol"; +import { TxBuilder } from "../src/contracts/helpers/TxBuilder.sol"; +import { UserOperationBuilder } from "./base/builders/UserOperationBuilder.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { DAppConfig } from "src/contracts/types/ConfigTypes.sol"; -import { SafeBlockNumber } from "src/contracts/libraries/SafeBlockNumber.sol"; -import "src/contracts/types/DAppOperation.sol"; +import { SolverOperation } from "../src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../src/contracts/types/UserOperation.sol"; +import { DAppConfig } from "../src/contracts/types/ConfigTypes.sol"; +import { DAppOperation } from "../src/contracts/types/DAppOperation.sol"; +import { SafeBlockNumber } from "../src/contracts/libraries/SafeBlockNumber.sol"; -import { V2RewardDAppControl } from "src/contracts/examples/v2-example-router/V2RewardDAppControl.sol"; -import { IUniswapV2Router01, IUniswapV2Router02 } from "src/contracts/examples/v2-example-router/interfaces/IUniswapV2Router.sol"; -import { SolverBase } from "src/contracts/solver/SolverBase.sol"; +import { V2RewardDAppControl } from "../src/contracts/examples/v2-example-router/V2RewardDAppControl.sol"; +import { IUniswapV2Router01, IUniswapV2Router02 } from "../src/contracts/examples/v2-example-router/interfaces/IUniswapV2Router.sol"; +import { SolverBase } from "../src/contracts/solver/SolverBase.sol"; contract V2RewardDAppControlTest is BaseTest { address V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; diff --git a/test/arbitrum/ArbGasInfoMock.sol b/test/arbitrum/ArbGasInfoMock.sol index d185768ed..304fd3e6e 100644 --- a/test/arbitrum/ArbGasInfoMock.sol +++ b/test/arbitrum/ArbGasInfoMock.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; contract ArbGasInfoMock { /// @notice Get gas prices. diff --git a/test/arbitrum/ArbitrumTest.t.sol b/test/arbitrum/ArbitrumTest.t.sol index ba400e507..76b89d1fc 100644 --- a/test/arbitrum/ArbitrumTest.t.sol +++ b/test/arbitrum/ArbitrumTest.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { BaseTest } from "../base/BaseTest.t.sol"; import { ArbSysMock } from "./ArbSysMock.sol"; diff --git a/test/base/ArbitrageTest.t.sol b/test/base/ArbitrageTest.t.sol index eda8080e9..2d7234a8b 100644 --- a/test/base/ArbitrageTest.t.sol +++ b/test/base/ArbitrageTest.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; diff --git a/test/base/BaseTest.t.sol b/test/base/BaseTest.t.sol index 78a30ce02..3353eb669 100644 --- a/test/base/BaseTest.t.sol +++ b/test/base/BaseTest.t.sol @@ -1,16 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import { FactoryLib } from "../../src/contracts/atlas/FactoryLib.sol"; import { TestAtlas } from "./TestAtlas.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; -import { ExecutionEnvironment } from "src/contracts/common/ExecutionEnvironment.sol"; -import { Sorter } from "src/contracts/helpers/Sorter.sol"; -import { Simulator } from "src/contracts/helpers/Simulator.sol"; -import { GovernanceBurner } from "src/contracts/helpers/GovernanceBurner.sol"; +import { AtlasVerification } from "../../src/contracts/atlas/AtlasVerification.sol"; +import { ExecutionEnvironment } from "../../src/contracts/common/ExecutionEnvironment.sol"; +import { Sorter } from "../../src/contracts/helpers/Sorter.sol"; +import { Simulator } from "../../src/contracts/helpers/Simulator.sol"; +import { GovernanceBurner } from "../../src/contracts/helpers/GovernanceBurner.sol"; contract BaseTest is Test { struct Sig { @@ -51,6 +52,8 @@ contract BaseTest is Test { IERC20 DAI = IERC20(DAI_ADDRESS); uint256 DEFAULT_ESCROW_DURATION = 64; + uint256 DEFAULT_ATLAS_SURCHARGE_RATE = 1_000_000; // 10% + uint256 DEFAULT_BUNDLER_SURCHARGE_RATE = 1_000_000; // 10% uint256 MAINNET_FORK_BLOCK = 17_441_786; function setUp() public virtual { @@ -83,15 +86,18 @@ contract BaseTest is Test { simulator = new Simulator(); // Computes the addresses at which AtlasVerification will be deployed - address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 1); - address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); + address expectedAtlasAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 2); + address expectedAtlasVerificationAddr = vm.computeCreateAddress(deployer, vm.getNonce(deployer) + 3); ExecutionEnvironment execEnvTemplate = new ExecutionEnvironment(expectedAtlasAddr); + FactoryLib factoryLib = new FactoryLib(address(execEnvTemplate)); atlas = new TestAtlas({ escrowDuration: DEFAULT_ESCROW_DURATION, + atlasSurchargeRate: DEFAULT_ATLAS_SURCHARGE_RATE, + bundlerSurchargeRate: DEFAULT_BUNDLER_SURCHARGE_RATE, verification: expectedAtlasVerificationAddr, simulator: address(simulator), - executionTemplate: address(execEnvTemplate), + factoryLib: address(factoryLib), initialSurchargeRecipient: deployer, l2GasCalculator: address(0) }); diff --git a/test/base/DummyDAppControl.sol b/test/base/DummyDAppControl.sol index e74653c17..dfd510a0a 100644 --- a/test/base/DummyDAppControl.sol +++ b/test/base/DummyDAppControl.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; +import { DAppControl } from "../../src/contracts/dapp/DAppControl.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; +import "../../src/contracts/types/ConfigTypes.sol"; +import "../../src/contracts/types/UserOperation.sol"; +import "../../src/contracts/types/SolverOperation.sol"; import "forge-std/Test.sol"; @@ -14,6 +14,22 @@ library CallConfigBuilder { } contract DummyDAppControl is DAppControl { + bool public preOpsShouldRevert; + bool public userOpShouldRevert; + bool public preSolverShouldRevert; + bool public postSolverShouldRevert; + bool public allocateValueShouldRevert; + bool public postOpsShouldRevert; + + bytes public preOpsInputData; + bytes public userOpInputData; + bytes public preSolverInputData; + bytes public postSolverInputData; + bytes public allocateValueInputData; + bytes public postOpsInputData; + + uint256 public userOpGasLeft; + event MEVPaymentSuccess(address bidToken, uint256 bidAmount); constructor( @@ -31,38 +47,37 @@ contract DummyDAppControl is DAppControl { function _checkUserOperation(UserOperation memory) internal pure virtual override { } function _preOpsCall(UserOperation calldata userOp) internal virtual override returns (bytes memory) { - if (userOp.data.length == 0) { - return new bytes(0); - } + bool shouldRevert = DummyDAppControl(CONTROL).preOpsShouldRevert(); + require(!shouldRevert, "_preOpsCall revert requested"); + + DummyDAppControl(CONTROL).setInputData(abi.encode(userOp), 0); + console.logBytes(abi.encode(userOp)); - (bool success, bytes memory data) = address(userOp.dapp).call(userOp.data); - require(success, "_preOpsCall reverted"); + if (userOp.data.length == 0) return new bytes(0); + + (, bytes memory data) = address(userOp.dapp).call(userOp.data); return data; } - function _postOpsCall(bool, bytes calldata data) internal pure virtual override { - if (data.length == 0) return; - - (bool shouldRevert) = abi.decode(data, (bool)); + function _postOpsCall(bool solved, bytes calldata data) internal virtual override { + bool shouldRevert = DummyDAppControl(CONTROL).postOpsShouldRevert(); require(!shouldRevert, "_postOpsCall revert requested"); - } - function _preSolverCall(SolverOperation calldata, bytes calldata returnData) internal view virtual override { - if (returnData.length == 0) { - return; - } + DummyDAppControl(CONTROL).setInputData(abi.encode(solved, data), 5); + } - (bool shouldRevert) = abi.decode(returnData, (bool)); + function _preSolverCall(SolverOperation calldata solverOp, bytes calldata returnData) internal virtual override { + bool shouldRevert = DummyDAppControl(CONTROL).preSolverShouldRevert(); require(!shouldRevert, "_preSolverCall revert requested"); - } - function _postSolverCall(SolverOperation calldata, bytes calldata returnData) internal pure virtual override { - if (returnData.length == 0) { - return; - } + DummyDAppControl(CONTROL).setInputData(abi.encode(solverOp, returnData), 2); + } - (bool shouldRevert) = abi.decode(returnData, (bool)); + function _postSolverCall(SolverOperation calldata solverOp, bytes calldata returnData) internal virtual override { + bool shouldRevert = DummyDAppControl(CONTROL).postSolverShouldRevert(); require(!shouldRevert, "_postSolverCall revert requested"); + + DummyDAppControl(CONTROL).setInputData(abi.encode(solverOp, returnData), 3); } function _allocateValueCall( @@ -74,13 +89,12 @@ contract DummyDAppControl is DAppControl { virtual override { - if (data.length == 0) { - return; - } - - (bool shouldRevert) = abi.decode(data, (bool)); + bool shouldRevert = DummyDAppControl(CONTROL).allocateValueShouldRevert(); require(!shouldRevert, "_allocateValueCall revert requested"); - emit MEVPaymentSuccess(bidToken, winningAmount); + + DummyDAppControl(CONTROL).setInputData(abi.encode(bidToken, winningAmount, data), 4); + + // emit MEVPaymentSuccess(bidToken, winningAmount); } function getBidValue(SolverOperation calldata solverOp) public view virtual override returns (uint256) { @@ -93,8 +107,68 @@ contract DummyDAppControl is DAppControl { // Custom functions // **************************************** - function userOperationCall(bool shouldRevert, uint256 returnValue) public pure returns (uint256) { + function userOperationCall(uint256 returnValue) public returns (uint256) { + DummyDAppControl(CONTROL).setUserOpGasLeft(); + + bool shouldRevert = DummyDAppControl(CONTROL).userOpShouldRevert(); require(!shouldRevert, "userOperationCall revert requested"); + + DummyDAppControl(CONTROL).setInputData(abi.encode(returnValue), 1); + return returnValue; } + + // Used to use all gas available during a call to get OOG error. + function burnEntireGasLimit() public { + uint256 _uselessSum; + while (true) { + _uselessSum += uint256(keccak256(abi.encodePacked(_uselessSum, gasleft()))) / 1e18; + } + } + + // Revert settings + + function setPreOpsShouldRevert(bool _preOpsShouldRevert) public { + preOpsShouldRevert = _preOpsShouldRevert; + } + + function setUserOpShouldRevert(bool _userOpShouldRevert) public { + userOpShouldRevert = _userOpShouldRevert; + } + + function setPreSolverShouldRevert(bool _preSolverShouldRevert) public { + preSolverShouldRevert = _preSolverShouldRevert; + } + + function setPostSolverShouldRevert(bool _postSolverShouldRevert) public { + postSolverShouldRevert = _postSolverShouldRevert; + } + + function setAllocateValueShouldRevert(bool _allocateValueShouldRevert) public { + allocateValueShouldRevert = _allocateValueShouldRevert; + } + + function setPostOpsShouldRevert(bool _postOpsShouldRevert) public { + postOpsShouldRevert = _postOpsShouldRevert; + } + + // Called by the EE to save input data for testing after the metacall ends + function setInputData( + bytes memory inputData, + uint256 hook // 0: preOps, 1: userOp, 2: preSolver, 3: postSolver, 4: allocateValue, 5: postOps + ) + public + { + if (hook == 0) preOpsInputData = inputData; + if (hook == 1) userOpInputData = inputData; + if (hook == 2) preSolverInputData = inputData; + if (hook == 3) postSolverInputData = inputData; + if (hook == 4) allocateValueInputData = inputData; + if (hook == 5) postOpsInputData = inputData; + } + + // Called by the EE to save gas left for testing at start of userOperationCall + function setUserOpGasLeft() public { + userOpGasLeft = gasleft(); + } } diff --git a/test/base/GasSponsorDAppControl.sol b/test/base/GasSponsorDAppControl.sol index 3de66a943..d6d676fbb 100644 --- a/test/base/GasSponsorDAppControl.sol +++ b/test/base/GasSponsorDAppControl.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { DAppControl } from "src/contracts/dapp/DAppControl.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { IExecutionEnvironment } from "src/contracts/interfaces/IExecutionEnvironment.sol"; +import { DAppControl } from "../../src/contracts/dapp/DAppControl.sol"; +import { IAtlas } from "../../src/contracts/interfaces/IAtlas.sol"; +import { IExecutionEnvironment } from "../../src/contracts/interfaces/IExecutionEnvironment.sol"; -import "src/contracts/types/ConfigTypes.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; +import "../../src/contracts/types/ConfigTypes.sol"; +import "../../src/contracts/types/UserOperation.sol"; +import "../../src/contracts/types/SolverOperation.sol"; import "forge-std/Test.sol"; diff --git a/test/base/TestAtlas.sol b/test/base/TestAtlas.sol index 4e325dc4c..80914b30a 100644 --- a/test/base/TestAtlas.sol +++ b/test/base/TestAtlas.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import "src/contracts/atlas/Atlas.sol"; +import "../../src/contracts/atlas/Atlas.sol"; /// @title TestAtlas /// @author FastLane Labs @@ -9,26 +9,38 @@ import "src/contracts/atlas/Atlas.sol"; contract TestAtlas is Atlas { constructor( uint256 escrowDuration, + uint256 atlasSurchargeRate, + uint256 bundlerSurchargeRate, address verification, address simulator, address initialSurchargeRecipient, address l2GasCalculator, - address executionTemplate + address factoryLib ) - Atlas(escrowDuration, verification, simulator, initialSurchargeRecipient, l2GasCalculator, executionTemplate) + Atlas( + escrowDuration, + atlasSurchargeRate, + bundlerSurchargeRate, + verification, + simulator, + initialSurchargeRecipient, + l2GasCalculator, + factoryLib + ) { } // Public functions to expose internal transient helpers for testing function clearTransientStorage() public { _setLock(address(0), 0, 0); - _setSolverLock(0); - _setSolverTo(address(0)); - _setClaims(0); - _setFees(0); - _setWriteoffs(0); - _setWithdrawals(0); - _setDeposits(0); + t_solverLock = 0; + t_solverTo = address(0); + t_claims = 0; + t_fees = 0; + t_writeoffs = 0; + t_withdrawals = 0; + t_deposits = 0; + t_solverSurcharge = 0; } function setLock(address activeEnvironment, uint32 callConfig, uint8 phase) public { @@ -40,52 +52,52 @@ contract TestAtlas is Atlas { } function setSolverLock(uint256 newSolverLock) public { - _setSolverLock(newSolverLock); + t_solverLock = newSolverLock; } function setSolverTo(address newSolverTo) public { - _setSolverTo(newSolverTo); + t_solverTo = newSolverTo; } function setClaims(uint256 newClaims) public { - _setClaims(newClaims); + t_claims = newClaims; } function setFees(uint256 newFees) public { - _setFees(newFees); + t_fees = newFees; } function setWriteoffs(uint256 newWriteoffs) public { - _setWriteoffs(newWriteoffs); + t_writeoffs = newWriteoffs; } function setWithdrawals(uint256 newWithdrawals) public { - _setWithdrawals(newWithdrawals); + t_withdrawals = newWithdrawals; } function setDeposits(uint256 newDeposits) public { - _setDeposits(newDeposits); + t_deposits = newDeposits; } - // View functions + // Transient Var View Functions - function getClaims() external view returns (uint256) { - return claims(); + function claims() external view returns (uint256) { + return t_claims; } - function getFees() external view returns (uint256) { - return fees(); + function fees() external view returns (uint256) { + return t_fees; } - function getWriteoffs() external view returns (uint256) { - return writeoffs(); + function writeoffs() external view returns (uint256) { + return t_writeoffs; } - function getWithdrawals() external view returns (uint256) { - return withdrawals(); + function withdrawals() external view returns (uint256) { + return t_withdrawals; } - function getDeposits() external view returns (uint256) { - return deposits(); + function deposits() external view returns (uint256) { + return t_deposits; } } diff --git a/test/base/TestUtils.sol b/test/base/TestUtils.sol index 50004d1ba..a3e942694 100644 --- a/test/base/TestUtils.sol +++ b/test/base/TestUtils.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { Mimic } from "src/contracts/common/Mimic.sol"; +import { IDAppControl } from "../../src/contracts/interfaces/IDAppControl.sol"; +import { Mimic } from "../../src/contracts/common/Mimic.sol"; -import "src/contracts/types/UserOperation.sol"; -import "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../../src/contracts/types/UserOperation.sol"; +import "../../src/contracts/types/SolverOperation.sol"; +import "../../src/contracts/types/ConfigTypes.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; +import { CallBits } from "../../src/contracts/libraries/CallBits.sol"; library TestUtils { using CallBits for uint32; diff --git a/test/base/builders/DAppOperationBuilder.sol b/test/base/builders/DAppOperationBuilder.sol index cf0979bba..4d45d6f94 100644 --- a/test/base/builders/DAppOperationBuilder.sol +++ b/test/base/builders/DAppOperationBuilder.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; -import "src/contracts/types/DAppOperation.sol"; +import { UserOperation } from "../../../src/contracts/types/UserOperation.sol"; +import { SolverOperation } from "../../../src/contracts/types/SolverOperation.sol"; +import "../../../src/contracts/types/DAppOperation.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; +import { CallVerification } from "../../../src/contracts/libraries/CallVerification.sol"; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IDAppControl } from "../../../src/contracts/interfaces/IDAppControl.sol"; +import { IAtlasVerification } from "../../../src/contracts/interfaces/IAtlasVerification.sol"; +import { IAtlas } from "../../../src/contracts/interfaces/IAtlas.sol"; -import "src/contracts/types/ConfigTypes.sol"; +import "../../../src/contracts/types/ConfigTypes.sol"; contract DAppOperationBuilder is Test { using CallVerification for UserOperation; diff --git a/test/base/builders/SolverOperationBuilder.sol b/test/base/builders/SolverOperationBuilder.sol index 4350ae75a..4130bb452 100644 --- a/test/base/builders/SolverOperationBuilder.sol +++ b/test/base/builders/SolverOperationBuilder.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { SolverOperation } from "src/contracts/types/SolverOperation.sol"; +import { UserOperation } from "../../../src/contracts/types/UserOperation.sol"; +import { SolverOperation } from "../../../src/contracts/types/SolverOperation.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; +import { CallVerification } from "../../../src/contracts/libraries/CallVerification.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; -import { IDAppControl } from "src/contracts/interfaces/IDAppControl.sol"; -import { IAtlas } from "src/contracts/interfaces/IAtlas.sol"; +import { IAtlas } from "../../../src/contracts/interfaces/IAtlas.sol"; +import { IAtlasVerification } from "../../../src/contracts/interfaces/IAtlasVerification.sol"; +import { IDAppControl } from "../../../src/contracts/interfaces/IDAppControl.sol"; +import { IAtlas } from "../../../src/contracts/interfaces/IAtlas.sol"; contract SolverOperationBuilder is Test { using CallVerification for UserOperation; diff --git a/test/base/builders/UserOperationBuilder.sol b/test/base/builders/UserOperationBuilder.sol index 26e24e56b..791642190 100644 --- a/test/base/builders/UserOperationBuilder.sol +++ b/test/base/builders/UserOperationBuilder.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { UserOperation } from "src/contracts/types/UserOperation.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; +import { UserOperation } from "../../../src/contracts/types/UserOperation.sol"; +import { CallConfig } from "../../../src/contracts/types/ConfigTypes.sol"; +import { CallBits } from "../../../src/contracts/libraries/CallBits.sol"; -import { IAtlasVerification } from "src/contracts/interfaces/IAtlasVerification.sol"; +import { IAtlasVerification } from "../../../src/contracts/interfaces/IAtlasVerification.sol"; contract UserOperationBuilder is Test { using CallBits for uint32; diff --git a/test/base/interfaces/IUniswapV2Router.sol b/test/base/interfaces/IUniswapV2Router.sol index aa198cf3c..3d45d23c2 100644 --- a/test/base/interfaces/IUniswapV2Router.sol +++ b/test/base/interfaces/IUniswapV2Router.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; interface IUniswapV2Router01 { function factory() external pure returns (address); diff --git a/test/gasCalculator/ArbitrumGasCalculator.t.sol b/test/gasCalculator/ArbitrumGasCalculator.t.sol index ccd99c20d..9f58b5ff2 100644 --- a/test/gasCalculator/ArbitrumGasCalculator.t.sol +++ b/test/gasCalculator/ArbitrumGasCalculator.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { ArbitrumGasCalculator } from "src/contracts/gasCalculator/ArbitrumGasCalculator.sol"; import { ArbGasInfoMock } from "../arbitrum/ArbGasInfoMock.sol"; @@ -12,7 +12,7 @@ contract ArbitrumGasCalculatorTest is ArbitrumTest { function setUp() public override { super.setUp(); // Deploy the calculator with initial values - calculator = new ArbitrumGasCalculator(0, false); + calculator = new ArbitrumGasCalculator(0); } function testGetCalldataCost() public { diff --git a/test/helpers/CallConfigBuilder.sol b/test/helpers/CallConfigBuilder.sol index cf3b57da7..97dbc2a94 100644 --- a/test/helpers/CallConfigBuilder.sol +++ b/test/helpers/CallConfigBuilder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; +import { CallConfig } from "../../src/contracts/types/ConfigTypes.sol"; import "forge-std/Test.sol"; diff --git a/test/helpers/DummyDAppControlBuilder.sol b/test/helpers/DummyDAppControlBuilder.sol index d9eaafd23..b86cf0037 100644 --- a/test/helpers/DummyDAppControlBuilder.sol +++ b/test/helpers/DummyDAppControlBuilder.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; -import { DummyDAppControl } from "test/base/DummyDAppControl.sol"; -import { CallConfig } from "src/contracts/types/ConfigTypes.sol"; -import { AtlasVerification } from "src/contracts/atlas/AtlasVerification.sol"; +import { DummyDAppControl } from "../base/DummyDAppControl.sol"; +import { CallConfig } from "../../src/contracts/types/ConfigTypes.sol"; +import { AtlasVerification } from "../../src/contracts/atlas/AtlasVerification.sol"; import "forge-std/Test.sol"; diff --git a/test/libraries/CallBits.t.sol b/test/libraries/CallBits.t.sol index ffc093cad..7d217a22e 100644 --- a/test/libraries/CallBits.t.sol +++ b/test/libraries/CallBits.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; -import "src/contracts/types/UserOperation.sol"; -import "test/base/TestUtils.sol"; +import { CallBits } from "../../src/contracts/libraries/CallBits.sol"; +import "../../src/contracts/types/UserOperation.sol"; +import "../base/TestUtils.sol"; contract CallBitsTest is Test { using CallBits for uint32; diff --git a/test/libraries/CallVerification.t.sol b/test/libraries/CallVerification.t.sol index 665224198..1861ee266 100644 --- a/test/libraries/CallVerification.t.sol +++ b/test/libraries/CallVerification.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { CallVerification } from "src/contracts/libraries/CallVerification.sol"; -import "src/contracts/types/UserOperation.sol"; -import "test/base/TestUtils.sol"; +import { CallVerification } from "../../src/contracts/libraries/CallVerification.sol"; +import "../../src/contracts/types/UserOperation.sol"; +import "../base/TestUtils.sol"; contract CallVerificationTest is Test { using CallVerification for UserOperation; diff --git a/test/libraries/EscrowBits.t.sol b/test/libraries/EscrowBits.t.sol index c404707d1..254cef218 100644 --- a/test/libraries/EscrowBits.t.sol +++ b/test/libraries/EscrowBits.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { EscrowBits } from "src/contracts/libraries/EscrowBits.sol"; -import "src/contracts/types/EscrowTypes.sol"; -import "test/base/TestUtils.sol"; +import { EscrowBits } from "../../src/contracts/libraries/EscrowBits.sol"; +import "../../src/contracts/types/EscrowTypes.sol"; +import "../base/TestUtils.sol"; contract EscrowBitsTest is Test { using EscrowBits for uint256; diff --git a/test/libraries/SafeBlockNumber.t.sol b/test/libraries/SafeBlockNumber.t.sol index bd6c60ecb..a851b9a73 100644 --- a/test/libraries/SafeBlockNumber.t.sol +++ b/test/libraries/SafeBlockNumber.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import { ArbitrumTest } from "../arbitrum/ArbitrumTest.t.sol"; import "forge-std/Test.sol"; diff --git a/test/libraries/SafetyBits.t.sol b/test/libraries/SafetyBits.t.sol index 52ba6c979..1ec221353 100644 --- a/test/libraries/SafetyBits.t.sol +++ b/test/libraries/SafetyBits.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.28; import "forge-std/Test.sol"; -import { SafetyBits } from "src/contracts/libraries/SafetyBits.sol"; -import "src/contracts/types/LockTypes.sol"; -import "test/base/TestUtils.sol"; +import { SafetyBits } from "../../src/contracts/libraries/SafetyBits.sol"; +import "../../src/contracts/types/LockTypes.sol"; +import "../base/TestUtils.sol"; -import { CallBits } from "src/contracts/libraries/CallBits.sol"; +import { CallBits } from "../../src/contracts/libraries/CallBits.sol"; -import { CallConfigIndex } from "src/contracts/types/ConfigTypes.sol"; +import { CallConfigIndex } from "../../src/contracts/types/ConfigTypes.sol"; contract SafetyBitsTest is Test { using SafetyBits for Context;