diff --git a/README.md b/README.md index 8d8bb9ae..9def81cd 100644 --- a/README.md +++ b/README.md @@ -65,16 +65,6 @@ Then, the test suite can be run with: pnpm run test ``` -#### Address Mismatch - -Many of the contracts (e.g. callbacks) require a specific address prefix or have a deterministic address. If tests are failing for this reason, the cause is usually one of: - -- The code of a callback contract has been changed - - This requires re-generating the salt for the contract. See the [test_salts.sh](/script/salts/test/test_salts.sh) script. -- There has been a change to the dependencies under `/lib` or `/dependencies`. The dependencies affect the build output, so any changes will affect the bytecode generated by the Solidity compiler. - - If the change was inadvertent, this can be fixed by running `pnpm install` to reset the changes. - - If the change to dependencies and invalidation of salts is expected, then new salts must be generated. In some cases (such as Uniswap V2 and V3 factories), the new addresses must be recorded in the `Constants.sol` file. - ### Format Combines `forge fmt` and `solhint` diff --git a/deployments/.berachain-v1.0.3.json b/deployments/.berachain-v1.0.3.json index 48e704dd..6796fa3e 100644 --- a/deployments/.berachain-v1.0.3.json +++ b/deployments/.berachain-v1.0.3.json @@ -1,7 +1,7 @@ { -"deployments.BatchAuctionHouse": "0xBA0000907c7812AEC8F7e9e27AefF4Ea7565A8bA", -"deployments.BatchCatalogue": "0x30c356DFBAc808BC62c860A9B285f024b40dF1fc", -"deployments.auctionModules.EncryptedMarginalPrice": "0x053219a03D5Bb08B8EeC2BB9743F723b312A1cE3", -"deployments.auctionModules.FixedPriceBatch": "0xe6c04Ce6ca70eeE60bEc40E2e6e62958D91E02CC", -"deployments.derivativeModules.BatchLinearVesting": "0xE292cF4e316191CbFEbD74909356DF3cd9455e96" + "deployments.BatchAuctionHouse": "0xBA0000907c7812AEC8F7e9e27AefF4Ea7565A8bA", + "deployments.BatchCatalogue": "0x30c356DFBAc808BC62c860A9B285f024b40dF1fc", + "deployments.auctionModules.EncryptedMarginalPrice": "0x053219a03D5Bb08B8EeC2BB9743F723b312A1cE3", + "deployments.auctionModules.FixedPriceBatch": "0xe6c04Ce6ca70eeE60bEc40E2e6e62958D91E02CC", + "deployments.derivativeModules.BatchLinearVesting": "0xE292cF4e316191CbFEbD74909356DF3cd9455e96" } diff --git a/foundry.toml b/foundry.toml index 24958d08..ebe6496e 100644 --- a/foundry.toml +++ b/foundry.toml @@ -32,4 +32,4 @@ forge-std = "1.9.1" solmate = "6.8.0" solady = "0.0.124" "@openzeppelin-contracts" = "4.9.2" -clones-with-immutable-args = { version = "1.1.1", git = "git@github.com:wighawag/clones-with-immutable-args.git", rev = "f5ca191afea933d50a36d101009b5644dc28bc99" } +clones-with-immutable-args = { version = "1.1.1", git = "https://github.com/wighawag/clones-with-immutable-args.git", rev = "f5ca191afea933d50a36d101009b5644dc28bc99" } diff --git a/script/deploy/deploy.sh b/script/deploy/deploy.sh index 4ffa68a1..5a458390 100755 --- a/script/deploy/deploy.sh +++ b/script/deploy/deploy.sh @@ -9,6 +9,9 @@ # RPC_URL: URL for the RPC node. Should be specified in .env. # VERIFIER_URL: URL for the Etherscan API verifier. Should be specified when used on an unsupported chain. +# Exit on error +set -e + # Iterate through named arguments # Source: https://unix.stackexchange.com/a/388038 while [ $# -gt 0 ]; do diff --git a/script/deploy/write_deployment.sh b/script/deploy/write_deployment.sh index 341405f7..13edbe79 100755 --- a/script/deploy/write_deployment.sh +++ b/script/deploy/write_deployment.sh @@ -4,6 +4,9 @@ # ./write_deployment.sh # Updates the env.json file with the key-value pair +# Exit on error +set -e + # Get command-line arguments KEY=$1 VALUE=$2 diff --git a/script/install.sh b/script/install.sh index b9c9cae2..bf032c43 100755 --- a/script/install.sh +++ b/script/install.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Exit on error +set -e + # echo "" # echo "*** Setting up submodules" # git submodule init diff --git a/script/publish.sh b/script/publish.sh index 8914d4cd..d69374a1 100755 --- a/script/publish.sh +++ b/script/publish.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Exit on error +set -e + # This script is used to release a new version of the package. It will: # - Validate that the working directory is clean # - Validate the version number argument diff --git a/script/salts/README.md b/script/salts/README.md index 34531d5e..ac3eb2e3 100644 --- a/script/salts/README.md +++ b/script/salts/README.md @@ -4,26 +4,6 @@ This document provides instructions on how to generate and use salts for CREATE2 ## Tasks -### Generating Test Salts - -Many of the tests use salts to deploy callbacks at addresses with a specific prefix. Changes to the state variables in the test contract can require the re-generation of the salt. To do so, perform the following: - -```bash -./script/salts/test/test_salts.sh --saltKey -``` - -For example, if re-generating salts for the `MockCallback` contract, make the following call: - -```bash -./script/salts/test/test_salts.sh --saltKey MockCallback -``` - -The resulting salts will be written to the `./script/salts/salts.json` file, which the test cases will read from. - -Notes: - -- When re-generating salts, ensure that any git submodule changes are either reverted or committed. For example, if switching from a branch with a particular submodule to a branch in which that submodule is not present, the submodule changes will not be automatically reverted. This will cause changes in the generated bytecode and in turn, the salt. The submodule changes must be reverted and the salts generated afterwards. - ### Generating AuctionHouse Salts For aesthetic reasons, the AuctionHouse contracts may need to be deployed at deterministic addresses. diff --git a/script/salts/WithSalts.s.sol b/script/salts/WithSalts.s.sol index 2f5035f2..cc706cbf 100644 --- a/script/salts/WithSalts.s.sol +++ b/script/salts/WithSalts.s.sol @@ -17,21 +17,18 @@ contract WithSalts is Script { } function _getBytecodePath( - string memory name_ + string memory name_, + bytes32 bytecodeHash_ ) internal pure returns (string memory) { - return string.concat(_getBytecodeDirectory(), "/", name_, ".bin"); + return string.concat( + _getBytecodeDirectory(), "/", name_, "-", vm.toString(bytecodeHash_), ".bin" + ); } function _createBytecodeDirectory() internal { // Create the bytecode folder if it doesn't exist if (!vm.isDir(_getBytecodeDirectory())) { - console2.log("Creating bytecode directory"); - - string[] memory inputs = new string[](2); - inputs[0] = "mkdir"; - inputs[1] = _BYTECODE_DIR; - - vm.ffi(inputs); + vm.createDir(_getBytecodeDirectory(), true); } } @@ -44,12 +41,55 @@ contract WithSalts is Script { bytes memory bytecode = abi.encodePacked(creationCode_, contractArgs_); bytecodeHash = keccak256(bytecode); - bytecodePath = _getBytecodePath(contractName_); + bytecodePath = _getBytecodePath(contractName_, bytecodeHash); + + // Don't write the bytecode if it already exists + if (vm.isFile(bytecodePath)) { + console2.log("Skipping bytecode write for ", contractName_); + return (bytecodePath, bytecodeHash); + } + + _createBytecodeDirectory(); vm.writeFile(bytecodePath, vm.toString(bytecode)); return (bytecodePath, bytecodeHash); } + function _generateSalt( + string memory contractName_, + bytes memory creationCode_, + bytes memory contractArgs_, + string memory prefix_ + ) internal returns (bytes32) { + // Write the bytecode + (string memory bytecodePath, bytes32 bytecodeHash) = + _writeBytecode(contractName_, creationCode_, contractArgs_); + + // Call the salts script to generate and return the salt + string[] memory inputs = new string[](9); + inputs[0] = "./script/salts/generate_salt.sh"; + inputs[1] = "--bytecodeFile"; + inputs[2] = bytecodePath; + inputs[3] = "--bytecodeHash"; + inputs[4] = vm.toString(bytecodeHash); + inputs[5] = "--prefix"; + inputs[6] = prefix_; + + bytes memory output = vm.ffi(inputs); + console2.log("Salt generated for", contractName_, "with prefix", prefix_); + console2.logBytes32(bytes32(output)); + + return bytes32(output); + } + + function _getTestSalt( + string memory contractName_, + bytes memory creationCode_, + bytes memory contractArgs_ + ) internal returns (bytes32) { + return _getSalt(string.concat("Test_", contractName_), creationCode_, contractArgs_); + } + /// @notice Gets the salt for a given key /// @dev If the key is not found, the function will return `bytes32(0)`. /// diff --git a/script/salts/generate_salt.sh b/script/salts/generate_salt.sh new file mode 100755 index 00000000..e24edbde --- /dev/null +++ b/script/salts/generate_salt.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Usage: +# ./generate_salt.sh --bytecode --prefix --bytecodeHash [--deployer ] + +# Exit on error +set -e + +# Iterate through named arguments +# Source: https://unix.stackexchange.com/a/388038 +while [ $# -gt 0 ]; do + if [[ $1 == *"--"* ]]; then + v="${1/--/}" + declare $v="$2" + fi + + shift +done + +# Check if bytecodeFile is set +if [ -z "$bytecodeFile" ] +then + echo "No bytecode file specified. Provide the relative path after the command." + exit 1 +fi + +# Check if bytecodeFile exists +if [ ! -f "$bytecodeFile" ] +then + echo "Bytecode file ($bytecodeFile) not found. Provide the correct relative path after the command." + exit 1 +fi + +# Check if prefix is set +if [ -z "$prefix" ] +then + echo "No prefix specified. Provide the prefix after the bytecode file." + exit 1 +fi + +# Check if bytecodeHash is set +if [ -z "$bytecodeHash" ] +then + echo "No args hash specified. Provide the args hash after the salt key." + exit 1 +fi + +DEPLOYER_FLAG="" +if [ ! -z "$deployer" ] +then + DEPLOYER_FLAG="--deployer $deployer" +fi + +# Generate salt using cast create2 +output=$(cast create2 --case-sensitive --starts-with $prefix --init-code $(cat $bytecodeFile) $DEPLOYER_FLAG) + +# Get the first salt (as cast will often return the same salt multiple times) +salt=$(echo "$output" | grep 'Salt: ' | head -n 1 | awk -F' ' '{print $2}') + +echo "$salt" diff --git a/script/salts/salts.json b/script/salts/salts.json index f70a5031..87f74533 100644 --- a/script/salts/salts.json +++ b/script/salts/salts.json @@ -25,25 +25,5 @@ "0xcad29ef747f1a7ad12c1e5e715ac675f8534c0d3682dfddfa39287ae7b7d7f01": "0x761de87b1ea43dc2f84665b59b2ce8498c1a09458e3a89751578be7c72811114", "0xf7e1693ed561ec566275117c8ea944263f9f801df4d4c61e4a934b7152f36dcc": "0x0b3e7731b05ed1f6d2cbbc4e64b503b8582801ae807ee756b3472916ec29c6fb", "0xf877dc218ee7538ffb3ad6f8fd1b4694cbb6f38d9e0b7a4d9a19ace3c24830a2": "0xad2a1f39589d55fd4fb667bda19d168106901d33100bb9c50fc57b1735024bcd" - }, - "Test_MockCallback": { - "0x122b7366cd1ef2d5b4e5301e1905912ec0fe8b73e77aee436d38421a86d15313": "0x0a9151c7b46dc91425f2a34eb6b2fb33ee191550a9165830ae27877b3f4ca221", - "0x31839cd002be9d58c711006d802d11286e56601f846dda258f2e3a3d6312e9d5": "0x413ec56e5cda12c513a637af386dc614c6d8d4cd3332147aa3c1e8a384357a78", - "0x3906ecd77f3b4704ca6c6d5a06ecf7039c68312b200ade661f6d2a28098049e1": "0xe9927b53dc310098994a46e7f6c2cd5104b776f99b91115eece80ec5f8acebe8", - "0x525f9fb7cb93f53509d24ec2f82f9d832e21209c45978e2e315915d6ff8c6a7f": "0xe900d098e9a5d9bb11ba2a3667b6b1eeae83814fe553bb76e514cf5b3fa7a2ac", - "0x54a5ad7b0937b5a5876975ca86a146047356b10210457afbbe77c13e6f5dd954": "0x8c917d14c4e8991eb770603f76c7a2ee6ec9938465f1b8e3c4bc144066179dac", - "0x6205fbf29817ca90fa2498c5b1187af9359d49f9386e35ba328382bcaa131cc3": "0x360e652e5304ee51b6e45d13472e12154037096162a58739e9407aae45926f01", - "0x678385a33025444b4cc1bb4114e4f2b91518f7b62874b3dc9c42cc273c353cb9": "0x55c1bb8e1768f6374b0d715192f3a4623af7018e5c4ccfae641766ff58ef6f53", - "0x780f4d36b46e5c008598b23b91a1a33d3a6d9a009ab4e7d1ec6c4fd0b96ae27e": "0x2e795045262fbbed80e54de0ee9a59506de844b46ffdcbf2fbfe6d2cb7bf6247", - "0x7dceb7e223c0a4949e5e2af68c3896c5549e9d942a7c0a2f82de4b4f1048467f": "0x384c9eafa40ee73af86d2d4fafdfd1ee31e06696f2c23a0c1d18b0e8785b6ce1", - "0x7fdc727348e9937fdf4d1ce371e33669ccd01a66514298047926c8cf38059721": "0x67567fd2ac4f9e05bda2cd306f73bb75aec8f0ce6ea6a60f00665b3ba7440b62", - "0x804b4adedbf071a753a22b7f14d78b78c9417097e5826cae690132d4b0d1598b": "0x8bb2239f825595560b0a31bb2bf07b18cd578df9dfb500b00c386eac3fd8b609", - "0x97c630af696c3e707d37a9df6f374aa2de8cbad3b57d70fd716c420aff85ee21": "0x32dbea5832194b7fa3c189f428b3abd9be5dc93d536c7799e7dbe122f0b9da89", - "0xb7e994be576e566138244c31d8ed1a61a2c2326f7850970f250734441540ba47": "0x3c1a8efebca923e4a1cdc651c554d06a3548e7929d0c7971866bf59b7d6571b3", - "0xb8efc6c465a7b9a95be1d788850dc2fc5372dc35032c8128b1ffec136000ed33": "0xb31bd2f0dada0bf7ceae9b37708c9329967684b9b73b7cc4a99027477b46b132", - "0xbc04d3cb883befcd89fc74569e56a84bf7adb63ae3864cbd1c11314d21c1355a": "0x4783fc51f9862eb57357966692ae70dd540e68ea0848903b77500534194b7f1c", - "0xc0c056f15966bf95b1fe024d064fdf5dc1ff953912a563bc162ff480bb29829d": "0x2eaeb172f8893ca0778cc5470e73f871ffc45825607e7fc37e15db3c369898a8", - "0xc51d6c63ad7dee6c11da98be8f32ac5ca7df37533c82928856a61da22d2e15dd": "0x19ce56b3efb04248482e4368f2063c9ea6f0ca1cedaced0737fa06ece52c43e1", - "0xdf57220126314faa7501d1bf9080691a765b85dcd73ddbc413ad43a5981beb82": "0x4be72c05d6c702b486af22bf4f9a29e0c0c466b036fee37355e9e7fb7c67b66d" } } diff --git a/script/salts/test/TestSalts.s.sol b/script/salts/test/TestSalts.s.sol deleted file mode 100644 index 533296aa..00000000 --- a/script/salts/test/TestSalts.s.sol +++ /dev/null @@ -1,365 +0,0 @@ -/// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -// Scripting libraries -import {Script} from "@forge-std-1.9.1/Script.sol"; -import {WithEnvironment} from "../../deploy/WithEnvironment.s.sol"; -import {Permit2User} from "../../../test/lib/permit2/Permit2User.sol"; -import {WithSalts} from "../WithSalts.s.sol"; - -import {MockCallback} from "../../../test/callbacks/MockCallback.sol"; -import {Callbacks} from "../../../src/lib/Callbacks.sol"; - -import {TestConstants} from "../../../test/Constants.sol"; - -contract TestSalts is Script, WithEnvironment, Permit2User, WithSalts, TestConstants { - string internal constant _MOCK_CALLBACK = "MockCallback"; - - function _setUp( - string calldata chain_ - ) internal { - _loadEnv(chain_); - _createBytecodeDirectory(); - } - - function generate(string calldata chain_, string calldata saltKey_) public { - _setUp(chain_); - - // For the given salt key, call the appropriate selector - // e.g. a salt key named MockCallback would require the following function: generateMockCallback() - bytes4 selector = bytes4(keccak256(bytes(string.concat("generate", saltKey_, "()")))); - - // Call the generate function for the salt key - (bool success,) = address(this).call(abi.encodeWithSelector(selector)); - require(success, string.concat("Failed to generate ", saltKey_)); - } - - function generateMockCallback() public { - // Allowlist callback supports onCreate, onPurchase, and onBid callbacks - // 10011000 = 0x98 - // cast create2 -s 98 -i $(cat ./bytecode/MockCallback98.bin) - bytes memory args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: false, - onCurate: false, - onPurchase: true, - onBid: true, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - bytes memory contractCode = type(MockCallback).creationCode; - (string memory bytecodePath, bytes32 bytecodeHash) = - _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "98", _MOCK_CALLBACK, bytecodeHash); - - // 11111111 = 0xFF - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: true, - onCurate: true, - onPurchase: true, - onBid: true, - onSettle: true, - receiveQuoteTokens: true, - sendBaseTokens: true - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "FF", _MOCK_CALLBACK, bytecodeHash); - - // 11111101 = 0xFD - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: true, - onCurate: true, - onPurchase: true, - onBid: true, - onSettle: true, - receiveQuoteTokens: false, - sendBaseTokens: true - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "FD", _MOCK_CALLBACK, bytecodeHash); - - // 11111110 = 0xFE - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: true, - onCurate: true, - onPurchase: true, - onBid: true, - onSettle: true, - receiveQuoteTokens: true, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "FE", _MOCK_CALLBACK, bytecodeHash); - - // 11111100 = 0xFC - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: true, - onCurate: true, - onPurchase: true, - onBid: true, - onSettle: true, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "FC", _MOCK_CALLBACK, bytecodeHash); - - // 00000000 - 0x00 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "00", _MOCK_CALLBACK, bytecodeHash); - - // 00000010 - 0x02 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: true, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "02", _MOCK_CALLBACK, bytecodeHash); - - // 10000000 = 0x80 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "80", _MOCK_CALLBACK, bytecodeHash); - - // 01000000 = 0x40 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: true, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "40", _MOCK_CALLBACK, bytecodeHash); - - // 00100000 = 0x20 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: true, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "20", _MOCK_CALLBACK, bytecodeHash); - - // 00010000 = 0x10 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: true, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "10", _MOCK_CALLBACK, bytecodeHash); - - // 00001000 = 0x08 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: true, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "08", _MOCK_CALLBACK, bytecodeHash); - - // 00000100 = 0x04 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: true, - receiveQuoteTokens: false, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "04", _MOCK_CALLBACK, bytecodeHash); - - // 00000010 = 0x02 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: true, - sendBaseTokens: false - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "02", _MOCK_CALLBACK, bytecodeHash); - - // 00000001 = 0x01 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: true - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "01", _MOCK_CALLBACK, bytecodeHash); - - // 10000001 = 0x81 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: false, - onCurate: false, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: true - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "81", _MOCK_CALLBACK, bytecodeHash); - - // 00100001 = 0x21 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: true, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: true - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "21", _MOCK_CALLBACK, bytecodeHash); - - // 10100001 = 0xA1 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: true, - onCancel: false, - onCurate: true, - onPurchase: false, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: true - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "A1", _MOCK_CALLBACK, bytecodeHash); - - // 00010001 = 0x11 - args = abi.encode( - _AUCTION_HOUSE, - Callbacks.Permissions({ - onCreate: false, - onCancel: false, - onCurate: false, - onPurchase: true, - onBid: false, - onSettle: false, - receiveQuoteTokens: false, - sendBaseTokens: true - }) - ); - (bytecodePath, bytecodeHash) = _writeBytecode(_MOCK_CALLBACK, contractCode, args); - _setTestSalt(bytecodePath, "11", _MOCK_CALLBACK, bytecodeHash); - } -} diff --git a/script/salts/test/test_salts.sh b/script/salts/test/test_salts.sh deleted file mode 100755 index f1dacaca..00000000 --- a/script/salts/test/test_salts.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# Usage: -# ./test_salts.sh --saltKey --envFile <.env> - -# Iterate through named arguments -# Source: https://unix.stackexchange.com/a/388038 -while [ $# -gt 0 ]; do - if [[ $1 == *"--"* ]]; then - v="${1/--/}" - declare $v="$2" - fi - - shift -done - -# Get the name of the .env file or use the default -ENV_FILE=${envFile:-".env"} -echo "Sourcing environment variables from $ENV_FILE" - -# Load environment file -set -a # Automatically export all variables -source $ENV_FILE -set +a # Disable automatic export - -# Check that the CHAIN environment variable is set -if [ -z "$CHAIN" ] -then - echo "CHAIN environment variable is not set. Please set it in the .env file or provide it as an environment variable." - exit 1 -fi - -# Check if saltKey is specified -if [ -z "$saltKey" ] -then - echo "No salt key specified. Provide the salt key after the --saltKey flag." - exit 1 -fi - -echo "Using chain: $CHAIN" -echo "Using RPC at URL: $RPC_URL" -echo "Salt key: $saltKey" - -salt_file="./script/salts/salts.json" -salt_tmp_file="./script/salts/salts.json.tmp" - -# Clear the salts for the specified salt key -if [ -f $salt_file ]; then - echo "Clearing old values for salt key: $saltKey" - jq "del(.\"Test_$saltKey\")" $salt_file > $salt_tmp_file && mv $salt_tmp_file $salt_file -fi - -# Generate bytecode -forge script ./script/salts/test/TestSalts.s.sol:TestSalts --sig "generate(string,string)()" $CHAIN $saltKey diff --git a/script/salts/write_salt.sh b/script/salts/write_salt.sh index 1ca8551c..d9ad6f93 100755 --- a/script/salts/write_salt.sh +++ b/script/salts/write_salt.sh @@ -3,6 +3,9 @@ # Usage: # ./write_salt.sh --bytecode --prefix --saltKey --bytecodeHash [--deployer ] +# Exit on error +set -e + # Iterate through named arguments # Source: https://unix.stackexchange.com/a/388038 while [ $# -gt 0 ]; do diff --git a/soldeer.lock b/soldeer.lock index 070185c9..1b59539b 100644 --- a/soldeer.lock +++ b/soldeer.lock @@ -1,30 +1,33 @@ +[[dependencies]] +name = "@openzeppelin-contracts" +version = "4.9.2" +url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/4_9_2_22-01-2024_13:13:52_contracts.zip" +checksum = "0f4450671798ea5659e6391876a3cf443ca50a696d9b556ac622ec7660bce306" +integrity = "f69bd90f264280204b2a1172a02a2d20f3611f5993a61e5215647bec696a8420" + +[[dependencies]] +name = "clones-with-immutable-args" +version = "1.1.1" +git = "https://github.com/wighawag/clones-with-immutable-args.git" +rev = "f5ca191afea933d50a36d101009b5644dc28bc99" [[dependencies]] name = "forge-std" version = "1.9.1" -source = "https://soldeer-revisions.s3.amazonaws.com/forge-std/v1_9_1_03-07-2024_14:44:59_forge-std-v1.9.1.zip" +url = "https://soldeer-revisions.s3.amazonaws.com/forge-std/v1_9_1_03-07-2024_14:44:59_forge-std-v1.9.1.zip" checksum = "110b35ad3604d91a919c521c71206c18cd07b29c750bd90b5cbbaf37288c9636" - -[[dependencies]] -name = "solmate" -version = "6.8.0" -source = "https://soldeer-revisions.s3.amazonaws.com/solmate/6_8_0_29-10-2024_19:01:45_solmate.zip" -checksum = "e3ec0f0182cb3bbedecf8a0bcc39897266534a795ec732b2b03dafa285d78a5b" +integrity = "389f8bfe6b6aad01915b1e38e6d4839f8189e8d4792b42be4e10d0a96a358e3f" [[dependencies]] name = "solady" version = "0.0.124" -source = "https://soldeer-revisions.s3.amazonaws.com/solady/0_0_124_22-01-2024_13:28:04_solady.zip" +url = "https://soldeer-revisions.s3.amazonaws.com/solady/0_0_124_22-01-2024_13:28:04_solady.zip" checksum = "9342385eaad08f9bb5408be0b41b241dd2b974c001f7da8c3b1ac552b52ce16b" +integrity = "29d93e52694d8e858cf5a737257f4a6f21aefccaf803174fd00b9d686172ab27" [[dependencies]] -name = "@openzeppelin-contracts" -version = "4.9.2" -source = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/4_9_2_22-01-2024_13:13:52_contracts.zip" -checksum = "0f4450671798ea5659e6391876a3cf443ca50a696d9b556ac622ec7660bce306" - -[[dependencies]] -name = "clones-with-immutable-args" -version = "1.1.1" -source = "git@github.com:wighawag/clones-with-immutable-args.git" -checksum = "f5ca191afea933d50a36d101009b5644dc28bc99" +name = "solmate" +version = "6.8.0" +url = "https://soldeer-revisions.s3.amazonaws.com/solmate/6_8_0_29-10-2024_19:01:45_solmate.zip" +checksum = "e3ec0f0182cb3bbedecf8a0bcc39897266534a795ec732b2b03dafa285d78a5b" +integrity = "a22e5a352de0231f671ee8adf5667bbe83c50012670083987bd1099a69feb429" diff --git a/test/AtomicAuctionHouse/AuctionHouseTest.sol b/test/AtomicAuctionHouse/AuctionHouseTest.sol index 73914b79..feeaac61 100644 --- a/test/AtomicAuctionHouse/AuctionHouseTest.sol +++ b/test/AtomicAuctionHouse/AuctionHouseTest.sol @@ -30,9 +30,10 @@ import {AuctionModule} from "../../src/modules/Auction.sol"; import {Veecode, toKeycode, keycodeFromVeecode, Keycode} from "../../src/modules/Keycode.sol"; -import {WithSalts} from "../lib/WithSalts.sol"; +import {WithSalts} from "../../script/salts/WithSalts.s.sol"; +import {TestConstants} from "../Constants.sol"; -abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts { +abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts, TestConstants { MockFeeOnTransferERC20 internal _baseToken; MockFeeOnTransferERC20 internal _quoteToken; @@ -51,7 +52,6 @@ abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts { uint256 internal constant _BASE_SCALE = 1e18; - address internal constant _OWNER = address(0x1); address internal constant _SELLER = address(0x2); address internal constant _PROTOCOL = address(0x3); address internal constant _CURATOR = address(0x4); @@ -106,7 +106,7 @@ abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts { // Create an AtomicAuctionHouse at a deterministic address, since it is used as input to callbacks AtomicAuctionHouse auctionHouse = new AtomicAuctionHouse(_OWNER, _PROTOCOL, _permit2Address); - _auctionHouse = AtomicAuctionHouse(address(0x000000000000000000000000000000000000000A)); + _auctionHouse = AtomicAuctionHouse(_AUCTION_HOUSE); vm.etch(address(_auctionHouse), address(auctionHouse).code); vm.store(address(_auctionHouse), bytes32(uint256(0)), bytes32(abi.encode(_OWNER))); // Owner vm.store(address(_auctionHouse), bytes32(uint256(6)), bytes32(abi.encode(1))); // Reentrancy @@ -272,6 +272,7 @@ abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts { modifier givenLotHasAllowlist() { // Get the salt + // 10011000 = 0x98 Callbacks.Permissions memory permissions = Callbacks.Permissions({ onCreate: true, onCancel: false, @@ -283,7 +284,7 @@ abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts { sendBaseTokens: false }); bytes memory args = abi.encode(address(_auctionHouse), permissions); - bytes32 salt = _getTestSalt("MockCallback", type(MockCallback).creationCode, args); + bytes32 salt = _generateSalt("MockCallback", type(MockCallback).creationCode, args, "98"); vm.startBroadcast(); // required for CREATE2 address to work correctly. doesn't do anything in a test _callback = new MockCallback{salt: salt}(address(_auctionHouse), permissions); @@ -367,6 +368,10 @@ abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts { modifier givenCallbackIsSet() { // Get the salt + // 11111100 = 0xFC + // 11111110 = 0xFE + // 11111111 = 0xFF + // 11111101 = 0xFD Callbacks.Permissions memory permissions = Callbacks.Permissions({ onCreate: true, onCancel: true, @@ -377,8 +382,16 @@ abstract contract AtomicAuctionHouseTest is Test, Permit2User, WithSalts { receiveQuoteTokens: _callbackReceiveQuoteTokens, sendBaseTokens: _callbackSendBaseTokens }); + string memory prefix = "FC"; + if (_callbackReceiveQuoteTokens && _callbackSendBaseTokens) { + prefix = "FF"; + } else if (_callbackReceiveQuoteTokens) { + prefix = "FE"; + } else if (_callbackSendBaseTokens) { + prefix = "FD"; + } bytes memory args = abi.encode(address(_auctionHouse), permissions); - bytes32 salt = _getTestSalt("MockCallback", type(MockCallback).creationCode, args); + bytes32 salt = _generateSalt("MockCallback", type(MockCallback).creationCode, args, prefix); // Required for CREATE2 address to work correctly. doesn't do anything in a test // Source: https://github.com/foundry-rs/foundry/issues/6402 diff --git a/test/AuctionHouse/sendPayment.t.sol b/test/AuctionHouse/sendPayment.t.sol index 4af2a14e..0ead95b7 100644 --- a/test/AuctionHouse/sendPayment.t.sol +++ b/test/AuctionHouse/sendPayment.t.sol @@ -9,12 +9,12 @@ import {MockFeeOnTransferERC20} from "../lib/mocks/MockFeeOnTransferERC20.sol"; import {Permit2User} from "../lib/permit2/Permit2User.sol"; import {Callbacks} from "../../src/lib/Callbacks.sol"; -import {WithSalts} from "../lib/WithSalts.sol"; +import {WithSalts} from "../../script/salts/WithSalts.s.sol"; +import {TestConstants} from "../Constants.sol"; -contract SendPaymentTest is Test, Permit2User, WithSalts { +contract SendPaymentTest is Test, Permit2User, WithSalts, TestConstants { MockAuctionHouse internal _auctionHouse; - address internal constant _OWNER = address(0x1); address internal constant _SELLER = address(0x2); address internal constant _PROTOCOL = address(0x3); address internal constant _USER = address(0x4); @@ -31,7 +31,7 @@ contract SendPaymentTest is Test, Permit2User, WithSalts { // Create an AuctionHouse at a deterministic address, since it is used as input to callbacks MockAuctionHouse mockAuctionHouse = new MockAuctionHouse(_OWNER, _PROTOCOL, _permit2Address); - _auctionHouse = MockAuctionHouse(address(0x000000000000000000000000000000000000000A)); + _auctionHouse = MockAuctionHouse(_AUCTION_HOUSE); vm.etch(address(_auctionHouse), address(mockAuctionHouse).code); vm.store(address(_auctionHouse), bytes32(uint256(0)), bytes32(abi.encode(_OWNER))); // Owner vm.store(address(_auctionHouse), bytes32(uint256(6)), bytes32(abi.encode(1))); // Reentrancy @@ -53,6 +53,8 @@ contract SendPaymentTest is Test, Permit2User, WithSalts { modifier givenAuctionHasCallback() { // Get the salt + // 00000000 = 0x00 + // 00000010 = 0x02 Callbacks.Permissions memory permissions = Callbacks.Permissions({ onCreate: false, onCancel: false, @@ -63,8 +65,12 @@ contract SendPaymentTest is Test, Permit2User, WithSalts { receiveQuoteTokens: _callbackReceiveQuoteTokens, sendBaseTokens: false }); + string memory prefix = "00"; + if (_callbackReceiveQuoteTokens) { + prefix = "02"; + } bytes memory args = abi.encode(address(_auctionHouse), permissions); - bytes32 salt = _getTestSalt("MockCallback", type(MockCallback).creationCode, args); + bytes32 salt = _generateSalt("MockCallback", type(MockCallback).creationCode, args, prefix); vm.broadcast(); // required for CREATE2 address to work correctly. doesn't do anything in a test _callback = new MockCallback{salt: salt}(address(_auctionHouse), permissions); diff --git a/test/BatchAuctionHouse/AuctionHouseTest.sol b/test/BatchAuctionHouse/AuctionHouseTest.sol index 001502bc..058c9490 100644 --- a/test/BatchAuctionHouse/AuctionHouseTest.sol +++ b/test/BatchAuctionHouse/AuctionHouseTest.sol @@ -30,9 +30,10 @@ import {AuctionModule} from "../../src/modules/Auction.sol"; import {Veecode, toKeycode, keycodeFromVeecode, Keycode} from "../../src/modules/Keycode.sol"; -import {WithSalts} from "../lib/WithSalts.sol"; +import {WithSalts} from "../../script/salts/WithSalts.s.sol"; +import {TestConstants} from "../Constants.sol"; -abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts { +abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts, TestConstants { MockFeeOnTransferERC20 internal _baseToken; MockFeeOnTransferERC20 internal _quoteToken; @@ -50,7 +51,6 @@ abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts { uint256 internal constant _BASE_SCALE = 1e18; - address internal constant _OWNER = address(0x1); address internal constant _SELLER = address(0x2); address internal constant _PROTOCOL = address(0x3); address internal constant _CURATOR = address(0x4); @@ -106,7 +106,7 @@ abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts { // Create a BatchAuctionHouse at a deterministic address, since it is used as input to callbacks BatchAuctionHouse auctionHouse = new BatchAuctionHouse(_OWNER, _PROTOCOL, _permit2Address); - _auctionHouse = BatchAuctionHouse(address(0x000000000000000000000000000000000000000A)); + _auctionHouse = BatchAuctionHouse(_AUCTION_HOUSE); vm.etch(address(_auctionHouse), address(auctionHouse).code); vm.store(address(_auctionHouse), bytes32(uint256(0)), bytes32(abi.encode(_OWNER))); // Owner vm.store(address(_auctionHouse), bytes32(uint256(6)), bytes32(abi.encode(1))); // Reentrancy @@ -325,6 +325,7 @@ abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts { modifier givenLotHasAllowlist() { // Get the salt + // 10011000 = 0x98 Callbacks.Permissions memory permissions = Callbacks.Permissions({ onCreate: true, onCancel: false, @@ -336,7 +337,7 @@ abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts { sendBaseTokens: false }); bytes memory args = abi.encode(address(_auctionHouse), permissions); - bytes32 salt = _getTestSalt("MockCallback", type(MockCallback).creationCode, args); + bytes32 salt = _generateSalt("MockCallback", type(MockCallback).creationCode, args, "98"); vm.startBroadcast(); // required for CREATE2 address to work correctly. doesn't do anything in a test _callback = new MockCallback{salt: salt}(address(_auctionHouse), permissions); @@ -420,6 +421,10 @@ abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts { modifier givenCallbackIsSet() { // Get the salt + // 11111100 = 0xFC + // 11111110 = 0xFE + // 11111111 = 0xFF + // 11111101 = 0xFD Callbacks.Permissions memory permissions = Callbacks.Permissions({ onCreate: true, onCancel: true, @@ -430,8 +435,16 @@ abstract contract BatchAuctionHouseTest is Test, Permit2User, WithSalts { receiveQuoteTokens: _callbackReceiveQuoteTokens, sendBaseTokens: _callbackSendBaseTokens }); + string memory prefix = "FC"; + if (_callbackReceiveQuoteTokens && _callbackSendBaseTokens) { + prefix = "FF"; + } else if (_callbackReceiveQuoteTokens) { + prefix = "FE"; + } else if (_callbackSendBaseTokens) { + prefix = "FD"; + } bytes memory args = abi.encode(address(_auctionHouse), permissions); - bytes32 salt = _getTestSalt("MockCallback", type(MockCallback).creationCode, args); + bytes32 salt = _generateSalt("MockCallback", type(MockCallback).creationCode, args, prefix); // Required for CREATE2 address to work correctly. doesn't do anything in a test // Source: https://github.com/foundry-rs/foundry/issues/6402 diff --git a/test/callbacks/Callbacks.t.sol b/test/callbacks/Callbacks.t.sol index 4eb6e9e5..264fc4bc 100644 --- a/test/callbacks/Callbacks.t.sol +++ b/test/callbacks/Callbacks.t.sol @@ -7,18 +7,19 @@ import {ICallback} from "../../src/interfaces/ICallback.sol"; import {MockCallback} from "./MockCallback.sol"; import {Test} from "@forge-std-1.9.1/Test.sol"; -import {WithSalts} from "../lib/WithSalts.sol"; +import {WithSalts} from "../../script/salts/WithSalts.s.sol"; +import {TestConstants} from "../Constants.sol"; -contract CallbacksTest is Test, WithSalts { +contract CallbacksTest is Test, WithSalts, TestConstants { using Callbacks for ICallback; - address internal constant _AUCTION_HOUSE = address(0x000000000000000000000000000000000000000A); - function _getMockCallbackSalt( - Callbacks.Permissions memory permissions_ + Callbacks.Permissions memory permissions_, + string memory prefix_ ) internal returns (bytes32) { bytes memory args = abi.encode(_AUCTION_HOUSE, permissions_); - return _getTestSalt("MockCallback", type(MockCallback).creationCode, args); + + return _generateSalt("MockCallback", type(MockCallback).creationCode, args, prefix_); } function _allFalseSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -34,7 +35,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "00"), permissions); } function _onCreateSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -50,7 +51,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "80"), permissions); } function _onCancelSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -66,7 +67,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "40"), permissions); } function _onCurateSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -82,7 +83,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "20"), permissions); } function _onPurchaseSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -98,7 +99,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "10"), permissions); } function _onBidSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -114,10 +115,11 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "08"), permissions); } function _onSettleSalt() internal returns (bytes32, Callbacks.Permissions memory) { + // 00000100 = 0x04 Callbacks.Permissions memory permissions = Callbacks.Permissions({ onCreate: false, onCancel: false, @@ -129,7 +131,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "04"), permissions); } function _receiveQuoteTokensSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -145,7 +147,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: false }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "02"), permissions); } function _sendBaseTokensSalt() internal returns (bytes32, Callbacks.Permissions memory) { @@ -161,7 +163,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: true }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "01"), permissions); } function _sendBaseTokens_onCreateSalt() @@ -180,7 +182,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: true }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "81"), permissions); } function _sendBaseTokens_onCurateSalt() @@ -199,7 +201,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: true }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "21"), permissions); } function _sendBaseTokens_onCreate_onCurateSalt() @@ -218,7 +220,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: true }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "A1"), permissions); } function _sendBaseTokens_onPurchaseSalt() @@ -237,7 +239,7 @@ contract CallbacksTest is Test, WithSalts { sendBaseTokens: true }); - return (_getMockCallbackSalt(permissions), permissions); + return (_getMockCallbackSalt(permissions, "11"), permissions); } // validateCallbacksPermissions @@ -401,6 +403,7 @@ contract CallbacksTest is Test, WithSalts { ); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_allFalse() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _allFalseSalt(); ICallback callback = _createCallback(salt, permissions); @@ -408,6 +411,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onCreate() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _onCreateSalt(); ICallback callback = _createCallback(salt, permissions); @@ -415,6 +419,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onCancel() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _onCancelSalt(); ICallback callback = _createCallback(salt, permissions); @@ -422,6 +427,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onCurate() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _onCurateSalt(); ICallback callback = _createCallback(salt, permissions); @@ -429,6 +435,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onPurchase() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _onPurchaseSalt(); ICallback callback = _createCallback(salt, permissions); @@ -436,6 +443,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onBid() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _onBidSalt(); ICallback callback = _createCallback(salt, permissions); @@ -443,6 +451,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onSettle() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _onSettleSalt(); ICallback callback = _createCallback(salt, permissions); @@ -450,6 +459,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onReceiveQuoteTokens() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _receiveQuoteTokensSalt(); ICallback callback = _createCallback(salt, permissions); @@ -457,6 +467,7 @@ contract CallbacksTest is Test, WithSalts { _assertValidateCallbacksPermissions(callback, permissions); } + /// forge-config: default.allow_internal_expect_revert = true function test_validateCallbacksPermissions_onSendBaseTokens() public { (bytes32 salt, Callbacks.Permissions memory permissions) = _sendBaseTokensSalt(); ICallback callback = _createCallback(salt, permissions); @@ -646,7 +657,7 @@ contract CallbacksTest is Test, WithSalts { // [X] if only RECEIVE_QUOTE_TOKENS_FLAG is set, return true // [X] if any callback function is set, return true - function test_isValidCallbacksAddress_zero() public { + function test_isValidCallbacksAddress_zero() public pure { ICallback callback = ICallback(address(0)); assertEq(callback.isValidCallbacksAddress(), true, "invalid"); diff --git a/test/lib/ECIES/decrypt.t.sol b/test/lib/ECIES/decrypt.t.sol index 4ca03596..af4ffb1a 100644 --- a/test/lib/ECIES/decrypt.t.sol +++ b/test/lib/ECIES/decrypt.t.sol @@ -20,6 +20,7 @@ contract ECIESDecryptTest is Test { function setUp() external {} + /// forge-config: default.allow_internal_expect_revert = true function testRevert_invalidPubKey() public { // Setup encryption parameters uint256 ciphertext = 1; @@ -33,6 +34,7 @@ contract ECIESDecryptTest is Test { ECIES.decrypt(ciphertext, ciphertextPubKey, recipientPrivateKey, salt); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_privateKeyTooLarge( uint256 privateKey_ ) public { @@ -49,6 +51,7 @@ contract ECIESDecryptTest is Test { ECIES.decrypt(ciphertext, ciphertextPubKey, privateKey_, salt); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_privateKeyZero() public { // Setup encryption parameters uint256 ciphertext = 1; @@ -62,7 +65,7 @@ contract ECIESDecryptTest is Test { ECIES.decrypt(ciphertext, ciphertextPubKey, privateKey, salt); } - function test_decrypt() public { + function test_decrypt() public view { // Setup encryption parameters uint256 ciphertext = 0xf96d7675ae04b89c9b5a9b0613d3530bb939186d05959efba9b3249a461abbc4; Point memory ciphertextPubKey = Point( @@ -84,7 +87,7 @@ contract ECIESDecryptTest is Test { uint256 salt_, uint256 recipientPrivKey_, uint256 messagePrivKey_ - ) public { + ) public view { vm.assume(recipientPrivKey_ > 0 && recipientPrivKey_ < ECIES.GROUP_ORDER); vm.assume(messagePrivKey_ > 0 && messagePrivKey_ < ECIES.GROUP_ORDER); diff --git a/test/lib/ECIES/encrypt.t.sol b/test/lib/ECIES/encrypt.t.sol index 179ed864..bedd7c31 100644 --- a/test/lib/ECIES/encrypt.t.sol +++ b/test/lib/ECIES/encrypt.t.sol @@ -9,6 +9,18 @@ import {ECIESFFITest} from "./ECIES_FFI.sol"; // ECIES import {Point, ECIES} from "../../../src/lib/ECIES.sol"; +contract EncryptWrapper { + function encrypt( + uint256 message_, + Point memory recipientPubKey_, + uint256 privateKey_, + uint256 salt_ + ) public view returns (uint256 ciphertext_, Point memory ciphertextPubKey_) { + (ciphertext_, ciphertextPubKey_) = + ECIES.encrypt(message_, recipientPubKey_, privateKey_, salt_); + } +} + contract ECIESEncryptTest is Test { // [X] when the public key is invalid // [X] it reverts @@ -18,21 +30,25 @@ contract ECIESEncryptTest is Test { // [X] it reverts // [X] it encrypts the message and provides the message pub key - function testFail_invalidPubKey() public view { + /// forge-config: default.allow_internal_expect_revert = true + function test_invalidPubKey_reverts() public { // Setup encryption parameters uint256 message = 1; Point memory recipientPubKey = Point(1, 1); uint256 privateKey = 1; uint256 salt = 1; - // Attempt to encrypt with an invalid public key, expect revert - // bytes memory err = abi.encodePacked("Invalid public key."); - // vm.expectRevert(err); - // For some reason, using expect revert causes the ecMul operation to fail. - // It seems to be a bug in the VM, so we use a generic fail test, which we've shown reverts correctly with stack traces. - ECIES.encrypt(message, recipientPubKey, privateKey, salt); + EncryptWrapper wrapper = new EncryptWrapper(); + + // Expect revert + vm.expectRevert("Invalid public key."); + + // For some reason, using expect revert causes the ecMul operation to fail when using the ECIES library directly. + // It seems to be a bug in the VM, so we wrap the call in another contract. + wrapper.encrypt(message, recipientPubKey, privateKey, salt); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_privateKeyTooLarge( uint256 privateKey_ ) public { @@ -49,6 +65,7 @@ contract ECIESEncryptTest is Test { ECIES.encrypt(message, recipientPubKey, privateKey_, salt); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_privateKeyZero() public { // Setup encryption parameters uint256 message = 1; @@ -62,7 +79,7 @@ contract ECIESEncryptTest is Test { ECIES.encrypt(message, recipientPubKey, privateKey, salt); } - function test_encrypt() public { + function test_encrypt() public view { // Setup encryption parameters uint256 message = 1; Point memory recipientPubKey = ECIES.calcPubKey(Point(1, 2), 2); @@ -92,7 +109,7 @@ contract ECIESEncryptTest is Test { uint256 salt_, uint256 recipientPrivKey_, uint256 messagePrivKey_ - ) public { + ) public view { vm.assume(recipientPrivKey_ > 0 && recipientPrivKey_ < ECIES.GROUP_ORDER); vm.assume(messagePrivKey_ > 0 && messagePrivKey_ < ECIES.GROUP_ORDER); @@ -134,7 +151,7 @@ contract ECIESEncryptTest is Test { console2.log("Gas used: ", startGas - endGas); } - function test_roundtrip() public { + function test_roundtrip() public view { // Setup encryption parameters uint256 message = 1; uint256 recipientPrivKey = 2; @@ -159,7 +176,7 @@ contract ECIESEncryptTest is Test { uint256 recipientPrivKey_, uint256 messagePrivKey_, uint256 salt_ - ) public { + ) public view { // Limit fuzz values since we do not allow private keys to be 0 or greater than the group order vm.assume(recipientPrivKey_ > 0 && recipientPrivKey_ < ECIES.GROUP_ORDER); vm.assume(messagePrivKey_ > 0 && messagePrivKey_ < ECIES.GROUP_ORDER); diff --git a/test/lib/MaxPriorityQueue.t.sol b/test/lib/MaxPriorityQueue.t.sol index 8bf6b597..b9a1ad38 100644 --- a/test/lib/MaxPriorityQueue.t.sol +++ b/test/lib/MaxPriorityQueue.t.sol @@ -303,6 +303,7 @@ contract MaxPriorityQueueTest is Test { assertEq(_queue.isEmpty(), true, "isEmpty mismatch"); } + /// forge-config: default.allow_internal_expect_revert = true function test_insert_zeroAmountOut_reverts() external { _queue.initialize(); @@ -334,6 +335,7 @@ contract MaxPriorityQueueTest is Test { assertEq(amountOut, 1e18); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_insert_bidAlreadyExists() external { _queue.initialize(); @@ -344,6 +346,7 @@ contract MaxPriorityQueueTest is Test { _queue.insert(_QUEUE_START, 0, 1, 1, _BASE_SCALE); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_insert_prevHintDoesNotExist() external { _queue.initialize(); @@ -355,6 +358,7 @@ contract MaxPriorityQueueTest is Test { _queue.insert(keyNotInQueue, 0, 1, 1, _BASE_SCALE); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_insert_bidHigherPriorityThanHint() external { _queue.initialize(); @@ -415,6 +419,8 @@ contract MaxPriorityQueueTest is Test { } // ========== delMax ========== // + + /// forge-config: default.allow_internal_expect_revert = true function testRevert_delMax_emptyQueue() external { _queue.initialize(); diff --git a/test/lib/WithSalts.sol b/test/lib/WithSalts.sol deleted file mode 100644 index d4eec62c..00000000 --- a/test/lib/WithSalts.sol +++ /dev/null @@ -1,44 +0,0 @@ -/// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "@forge-std-1.9.1/Test.sol"; -import {stdJson} from "@forge-std-1.9.1/StdJson.sol"; - -contract WithSalts is Test { - using stdJson for string; - - string internal constant _SALTS_PATH = "./script/salts/salts.json"; - string internal _saltJson; - - /// @notice Gets the salt for a given key - /// @dev Test salts are read from underneath the ".test" prefix. - /// - /// If the key is not found, the function will return `bytes32(0)`. - /// - /// @param contractName_ The contract to get the salt for - /// @param contractCode_ The creation code of the contract - /// @param args_ The abi-encoded constructor arguments to the contract - /// @return The salt for the given key - function _getTestSalt( - string memory contractName_, - bytes memory contractCode_, - bytes memory args_ - ) internal returns (bytes32) { - // Load salt file if needed - if (bytes(_saltJson).length == 0) { - _saltJson = vm.readFile(_SALTS_PATH); - } - - // Generate the bytecode hash - bytes memory bytecode = abi.encodePacked(contractCode_, args_); - bytes32 bytecodeHash = keccak256(bytecode); - - bytes32 salt = bytes32( - vm.parseJson( - _saltJson, string.concat(".Test_", contractName_, ".", vm.toString(bytecodeHash)) - ) - ); - - return salt; - } -} diff --git a/test/modules/Modules/Keycode.t.sol b/test/modules/Modules/Keycode.t.sol index d7040b6e..0d74228f 100644 --- a/test/modules/Modules/Keycode.t.sol +++ b/test/modules/Modules/Keycode.t.sol @@ -16,19 +16,19 @@ import { } from "../../../src/modules/Modules.sol"; contract KeycodeTest is Test { - function test_keycode() external { + function test_keycode() external pure { Keycode keycode = toKeycode("TEST"); assertEq(fromKeycode(keycode), "TEST"); } - function test_ensureValidVeecode_singleDigitNumber() external { + function test_ensureValidVeecode_singleDigitNumber() external pure { Keycode keycode = toKeycode("TEST"); Veecode t1Veecode = wrapVeecode(keycode, 1); ensureValidVeecode(t1Veecode); } - function test_ensureValidVeecode_doubleDigitNumber() external { + function test_ensureValidVeecode_doubleDigitNumber() external pure { Keycode keycode = toKeycode("TEST"); Veecode t1Veecode = wrapVeecode(keycode, 11); @@ -45,7 +45,7 @@ contract KeycodeTest is Test { return bytes5(keycodeBytes); } - function test_ensureValidVeecode_length() external { + function test_ensureValidVeecode_length() external pure { Keycode t1Keycode = toKeycode("TES"); Veecode t1Veecode = wrapVeecode(t1Keycode, 11); ensureValidVeecode(t1Veecode); @@ -66,6 +66,7 @@ contract KeycodeTest is Test { assertFalse(fromVeecode(t3Veecode) == fromVeecode(t4Veecode)); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_ensureValidVeecode_invalidRequiredCharacter( uint8 character_, uint8 index_ @@ -88,6 +89,7 @@ contract KeycodeTest is Test { ensureValidVeecode(t1Veecode); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_ensureValidVeecode_invalidOptionalCharacter( uint8 character_, uint8 index_ @@ -110,6 +112,7 @@ contract KeycodeTest is Test { ensureValidVeecode(t1Veecode); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_ensureValidVeecode_zeroVersion() external { Keycode keycode = toKeycode("TEST"); Veecode t1Veecode = wrapVeecode(keycode, 0); @@ -120,6 +123,7 @@ contract KeycodeTest is Test { ensureValidVeecode(t1Veecode); } + /// forge-config: default.allow_internal_expect_revert = true function testRevert_ensureValidVeecode_invalidVersion( uint8 version_ ) external { @@ -135,7 +139,7 @@ contract KeycodeTest is Test { ensureValidVeecode(t1Veecode); } - function test_unwrapVeecode() external { + function test_unwrapVeecode() external pure { Keycode keycode = toKeycode("TEST"); Veecode t1Veecode = wrapVeecode(keycode, 1); (Keycode keycode_, uint8 moduleVersion_) = unwrapVeecode(t1Veecode);