diff --git a/CHANGELOG.md b/CHANGELOG.md index 2743d84ee..34e2e31a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,16 @@ Master list of UniV3 forks: * Add `DODOV1` action to Mantle * Add `DODOV1` action to Polygon * Add `DODOV1` action to Scroll +* Add `rebateClaimer()(address)` function on Mainnet Settlers for gas rebate program + +## 2024-12-18 + +### Breaking changes + +### Non-breaking changes + +* Deploy Settler to Ink chain + * Add UniswapV3 UniV3 fork to Ink ## 2024-12-14 diff --git a/README.md b/README.md index b3f354f60..b13920c51 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ your integration. * `0x0000000000001fF3684f28c67538d4D072C22734` on chains supporting the Cancun hardfork (Ethereum Mainnet, Ethereum Sepolia, Polygon, Base, Optimism, - Arbitrum, Blast, Bnb, Mode, World Chain, Gnosis, Fantom Sonic) + Arbitrum, Blast, Bnb, Mode, World Chain, Gnosis, Fantom Sonic, Ink) * `0x0000000000005E88410CcDFaDe4a5EfaE4b49562` on chains supporting the Shanghai hardfork (Avalanche, Scroll, Mantle, Taiko) * `0x000000000000175a8b9bC6d539B3708EEd92EA6c` on chains supporting the London diff --git a/api_secrets.json.template b/api_secrets.json.template index c0aef9435..dea7cdc02 100644 --- a/api_secrets.json.template +++ b/api_secrets.json.template @@ -64,5 +64,8 @@ "sonic": { "etherscanKey": "", "rpcUrl": "" + }, + "ink": { + "rpcUrl": "" } } diff --git a/chain_config.json b/chain_config.json index c1f31e325..d56f6daf4 100644 --- a/chain_config.json +++ b/chain_config.json @@ -440,5 +440,31 @@ "deployer": "0x00000000000004533Fe15556B1E086BB1A72cEae" }, "etherscanApi": "https://api.sonicscan.org/api" + }, + "ink": { + "chainId": 57073, + "displayName": "Ink", + "isShanghai": true, + "isCancun": true, + "extraFlags": "--legacy", + "gasMultiplierPercent": 200, + "minGasPriceGwei": 1, + "safe": { + "singleton": "0xfb1bffC9d739B8D520DaF37dF666da4C687191EA", + "factory": "0xC22834581EbC8527d974F8a1c97E1bEA4EF910BC", + "fallback": "0x017062a1dE2FE6b99BE3d9d37841FeD19F573804", + "multiCall": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "apiUrl": "https://safe-transaction-ink.safe.global/api" + }, + "governance": { + "upgradeSafe": "0xf36b9f50E59870A24F42F9Ba43b2aD0A4b8f2F51", + "deploymentSafe": "0x8E5DE7118a596E99B0563D3022039c11927f4827", + "pause": "0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30" + }, + "deployment": { + "deployer": "0x00000000000004533Fe15556B1E086BB1A72cEae", + "allowanceHolder": "0x0000000000001fF3684f28c67538d4D072C22734" + }, + "blockscoutApi": "https://explorer.inkonchain.com/api" } } diff --git a/script/SafeConfig.sol b/script/SafeConfig.sol index 37883dbb2..e03bb761c 100644 --- a/script/SafeConfig.sol +++ b/script/SafeConfig.sol @@ -23,6 +23,7 @@ library SafeConfig { || block.chainid == 34443 // mode || block.chainid == 42161 // arbitrum || block.chainid == 43114 // avalanche + || block.chainid == 57073 // ink || block.chainid == 59144 // linea || block.chainid == 81457 // blast || block.chainid == 167000 // taiko @@ -49,6 +50,7 @@ library SafeConfig { || block.chainid == 34443 // mode || block.chainid == 42161 // arbitrum || block.chainid == 43114 // avalanche + || block.chainid == 57073 // ink || block.chainid == 59144 // linea || block.chainid == 81457 // blast || block.chainid == 167000 // taiko @@ -86,7 +88,7 @@ library SafeConfig { result[0] = 0x24420bC8C760787F3eEF3b809e81f44d31a9c5A2; // Jacob result[1] = 0x000000c397124D0375555F435e201F83B636C26C; // Kyu result[2] = 0x6879fAb591ed0d62537A3Cac9D7cd41218445a84; // Sav - result[3] = 0x755588A2422E4779aC30cBD3774BBB12521d2c15; // Josh + result[3] = 0x052809d05DC83F317b2f578710411e6cbF88AC5a; // Josh result[4] = 0xDCa4ee0070b4aa44b30D8af22F3CBbb2cC859dAf; // Kevin result[5] = 0xD6B66609E5C05210BE0A690aB3b9788BA97aFa60; // Duncan result[6] = 0xEC3E1F7aC9Df42c31570b02068f2e7500915e557; // Andy diff --git a/sh/common.sh b/sh/common.sh index 4f7507a7f..2361d0166 100644 --- a/sh/common.sh +++ b/sh/common.sh @@ -50,20 +50,26 @@ function get_config { jq -Mr ."$chain_name"."$1" < "$project_root"/chain_config.json } -if [[ $(get_config isShanghai) != [Tt]rue ]] ; then - echo 'Chains without the Shanghai hardfork (PUSH0) are not supported' >&2 - exit 1 -fi +if [[ ${IGNORE_HARDFORK-no} != [Yy]es ]] ; then + if [[ $(get_config isShanghai) != [Tt]rue ]] ; then + echo 'Chains without the Shanghai hardfork (PUSH0) are not supported' >&2 + exit 1 + fi -if [[ $(get_config isCancun) != [Tt]rue ]] ; then - echo 'You are on the wrong branch' >&2 - exit 1 + if [[ $(get_config isCancun) != [Tt]rue ]] ; then + echo 'You are on the wrong branch' >&2 + exit 1 + fi fi declare -i chainid chainid="$(get_config chainId)" declare -r -i chainid +declare chain_display_name +chain_display_name="$(get_config displayName)" +declare -r chain_display_name + declare rpc_url rpc_url="$(get_api_secret rpcUrl)" declare -r rpc_url @@ -81,12 +87,12 @@ function verify_contract { declare -r _verify_source_path="$1" shift - if (( chainid == 34443 )) ; then # Mode uses Blockscout, not Etherscan + if (( chainid == 34443 )) || (( chainid == 57073 )) ; then # Mode and Ink use Blockscout, not Etherscan forge verify-contract --watch --chain $chainid --verifier blockscout --verifier-url "$(get_config blockscoutApi)" --constructor-args "$_verify_constructor_args" "$_verify_deployed_address" "$_verify_source_path" else forge verify-contract --watch --chain $chainid --verifier custom --verifier-api-key "$(get_api_secret etherscanKey)" --verifier-url "$(get_config etherscanApi)" --constructor-args "$_verify_constructor_args" "$_verify_deployed_address" "$_verify_source_path" fi - if (( chainid != 146 )) && (( chainid != 480 )) && (( chainid != 81457 )) && (( chainid != 167000 )); then # Sourcify doesn't support Sonic, World Chain, Blast, or Taiko + if (( chainid != 146 )) && (( chainid != 480 )) && (( chainid != 57073 )) && (( chainid != 81457 )) && (( chainid != 167000 )); then # Sourcify doesn't support Sonic, World Chain, Blast, Taiko, or Ink forge verify-contract --watch --chain $chainid --verifier sourcify --constructor-args "$_verify_constructor_args" "$_verify_deployed_address" "$_verify_source_path" fi } diff --git a/sh/common_deploy_settler.sh b/sh/common_deploy_settler.sh index e35f7395c..50e9df412 100644 --- a/sh/common_deploy_settler.sh +++ b/sh/common_deploy_settler.sh @@ -1,7 +1,3 @@ -declare chain_display_name -chain_display_name="$(get_config displayName)" -declare -r chain_display_name - forge clean declare flat_taker_source flat_taker_source="$project_root"/src/flat/"$chain_display_name"TakerSubmittedFlat.sol @@ -84,7 +80,3 @@ if [[ -n "${deployer_address-}" ]] ; then ) fi fi - -declare safe_url -safe_url="$(get_config safe.apiUrl)" -declare -r safe_url diff --git a/sh/common_safe.sh b/sh/common_safe.sh index e79559c8a..6409d58fc 100644 --- a/sh/common_safe.sh +++ b/sh/common_safe.sh @@ -1,3 +1,8 @@ + +declare safe_url +safe_url="$(get_config safe.apiUrl)" +declare -r safe_url + declare multicall_address multicall_address="$(get_config safe.multiCall)" declare -r multicall_address @@ -13,6 +18,42 @@ nonce() { echo $((${SAFE_NONCE_INCREMENT:-0} + current_safe_nonce)) } +declare -r get_owners_sig='getOwners()(address[])' +declare owners +owners="$(cast call --rpc-url "$rpc_url" "$safe_address" "$get_owners_sig")" +owners="${owners:1:$((${#owners} - 2))}" +owners="${owners//, /;}" +declare -r owners + +declare -a owners_array +IFS=';' read -r -a owners_array <<<"$owners" +declare -r -a owners_array + +prev_owner() { + declare inp="$1" + shift + inp="$(cast to-checksum "$inp")" + declare -r inp + + declare result=0x0000000000000000000000000000000000000001 + declare owner_i + for i in ${!owners_array[@]} ; do + owner_i="$(cast to-checksum "${owners_array[$i]}")" + if [[ $owner_i = "$inp" ]] ; then + break + fi + result="$owner_i" + done + declare -r result + + if [[ $result = "$(cast to-checksum "${owners_array[$((${#owners_array} - 1))]}")" ]] ; then + echo 'Old owner "'"$inp"'" not found' >&2 + return 1 + fi + + echo "$result" +} + target() { declare -i operation if (( $# > 0 )) ; then @@ -64,6 +105,15 @@ eip712_json() { fi declare -r -i operation + declare to + if (( $# > 0 )) ; then + to="$1" + shift + else + to="$(target $operation)" + fi + declare -r to + jq -Mc \ ' { @@ -132,7 +182,7 @@ eip712_json() { ' \ --arg verifyingContract "$safe_address" \ --arg chainId "$chainid" \ - --arg to "$(target $operation)" \ + --arg to "$to" \ --arg data "$calldata" \ --arg operation $operation \ --arg nonce $(nonce) \ @@ -152,7 +202,16 @@ eip712_struct_hash() { fi declare -r -i operation - cast keccak "$(cast abi-encode 'foo(bytes32,address,uint256,bytes32,uint8,uint256,uint256,uint256,address,address,uint256)' "$type_hash" "$(target $operation)" 0 "$(cast keccak "$calldata")" $operation 0 0 0 "$(cast address-zero)" "$(cast address-zero)" $(nonce))" + declare to + if (( $# > 0 )) ; then + to="$1" + shift + else + to="$(target $operation)" + fi + declare -r to + + cast keccak "$(cast abi-encode 'foo(bytes32,address,uint256,bytes32,uint8,uint256,uint256,uint256,address,address,uint256)' "$type_hash" "$to" 0 "$(cast keccak "$calldata")" $operation 0 0 0 "$(cast address-zero)" "$(cast address-zero)" $(nonce))" } eip712_hash() { @@ -168,8 +227,17 @@ eip712_hash() { fi declare -r -i operation + declare to + if (( $# > 0 )) ; then + to="$1" + shift + else + to="$(target $operation)" + fi + declare -r to + declare struct_hash - struct_hash="$(eip712_struct_hash "$calldata" $operation)" + struct_hash="$(eip712_struct_hash "$calldata" $operation "$to")" cast keccak "$(cast concat-hex '0x1901' "$domain_separator" "$struct_hash")" } diff --git a/sh/common_safe_deployer.sh b/sh/common_safe_deployer.sh new file mode 100644 index 000000000..2c947b7f6 --- /dev/null +++ b/sh/common_safe_deployer.sh @@ -0,0 +1,63 @@ +retrieve_signatures() { + declare -r _retrieve_signatures_prefix="$1" + shift + + declare -r _retrieve_signatures_call="$1" + shift + + declare -i _retrieve_signatures_operation + if (( $# > 0 )) ; then + _retrieve_signatures_operation="$1" + shift + else + _retrieve_signatures_operation=0 + fi + declare -r -i _retrieve_signatures_operation + + declare _retrieve_signatures_to + if (( $# > 0 )) ; then + _retrieve_signatures_to="$1" + shift + else + _retrieve_signatures_to="$(target $_retrieve_signatures_operation)" + fi + declare -r _retrieve_signatures_to + + declare signing_hash + signing_hash="$(eip712_hash "$_retrieve_signatures_call" $_retrieve_signatures_operation "$_retrieve_signatures_to")" + declare -r signing_hash + + declare -a _retrieve_signatures_result + if [[ $safe_url = 'NOT SUPPORTED' ]] ; then + set +f + declare confirmation + for confirmation in "$project_root"/"$_retrieve_signatures_prefix"_"$chain_display_name"_"$(git rev-parse --short=8 HEAD)"_*_$(nonce).txt ; do + signatures+=("$(<"$confirmation")") + done + set -f + + if (( ${#signatures[@]} != 2 )) ; then + echo 'Bad number of signatures' >&2 + return 1 + fi + else + declare signatures_json + signatures_json="$(curl --fail -s "$safe_url"'/v1/multisig-transactions/'"$signing_hash"'/confirmations/?executed=false' -X GET)" + declare -r signatures_json + + if (( $(jq -Mr .count <<<"$signatures_json") != 2 )) ; then + echo 'Bad number of signatures' >&2 + return 1 + fi + + if [ "$(jq -Mr '.results[1].owner' <<<"$signatures_json" | tr '[:upper:]' '[:lower:]')" \< "$(jq -Mr '.results[0].owner' <<<"$signatures_json" | tr '[:upper:]' '[:lower:]')" ] ; then + signatures+=( "$(jq -Mr '.results[1].signature' <<<"$signatures_json")" ) + signatures+=( "$(jq -Mr '.results[0].signature' <<<"$signatures_json")" ) + else + signatures+=( "$(jq -Mr '.results[0].signature' <<<"$signatures_json")" ) + signatures+=( "$(jq -Mr '.results[1].signature' <<<"$signatures_json")" ) + fi + fi + + cast concat-hex "${signatures[@]}" +} diff --git a/sh/common_safe_owner.sh b/sh/common_safe_owner.sh index 8fba2730f..be475ab8b 100644 --- a/sh/common_safe_owner.sh +++ b/sh/common_safe_owner.sh @@ -1,14 +1,3 @@ -declare -r get_owners_sig='getOwners()(address[])' -declare owners -owners="$(cast abi-decode "$get_owners_sig" "$(cast call --rpc-url "$rpc_url" "$safe_address" "$(cast calldata "$get_owners_sig")")")" -owners="${owners:1:$((${#owners} - 2))}" -owners="${owners//, /;}" -declare -r owners - -declare -a owners_array -IFS=';' read -r -a owners_array <<<"$owners" -declare -r -a owners_array - declare signer declare -r saved_safe_owner="$project_root"/config/safe_owner.txt @@ -43,3 +32,109 @@ if ! contains "${signer-unset}" "${owners_array[@]}" ; then fi declare -r signer + +sign_call() { + declare -r _sign_call_struct_json="$1" + shift + + declare _sign_call_result + if [[ $wallet_type = 'frame' ]] ; then + declare typedDataRPC + typedDataRPC="$( + jq -Mc \ + ' + { + "jsonrpc": "2.0", + "method": "eth_signTypedData", + "params": [ + $signer, + . + ], + "id": 1 + } + ' \ + --arg signer "$signer" \ + <<<"$_sign_call_struct_json" + )" + declare -r typedDataRPC + _sign_call_result="$(curl --fail -s -X POST --url 'http://127.0.0.1:1248' --data "$typedDataRPC")" + if [[ $_sign_call_result = *error* ]] ; then + echo "$_sign_call_result" >&2 + return 1 + fi + _sign_call_result="$(jq -Mr .result <<<"$_sign_call_result")" + else + _sign_call_result="$(cast wallet sign "${wallet_args[@]}" --from "$signer" --data "$_sign_call_struct_json")" + fi + declare -r _sign_call_result + + echo "$_sign_call_result" +} + +save_signature() { + declare -r _save_signature_prefix="$1" + shift + + declare -r _save_signature_call="$1" + shift + + declare -r _save_signature_signature="$1" + shift + + declare -i _save_signature_operation + if (( $# > 0 )) ; then + _save_signature_operation="$1" + shift + else + _save_signature_operation=0 + fi + declare -r -i _save_signature_operation + + declare _save_signature_to + if (( $# > 0 )) ; then + _save_signature_to="$1" + shift + else + _save_signature_to="$(target $_save_signature_operation)" + fi + declare -r _save_signature_to + + if [[ $safe_url = 'NOT SUPPORTED' ]] ; then + declare signature_file + signature_file="$project_root"/"$_save_signature_prefix"_"$chain_display_name"_"$(git rev-parse --short=8 HEAD)"_"$(tr '[:upper:]' '[:lower:]' <<<"$signer")"_$(nonce).txt + echo "$signature" >"$signature_file" + + echo "Signature saved to '$signature_file'" >&2 + else + declare signing_hash + signing_hash="$(eip712_hash "$_save_signature_call" $_save_signature_operation "$_save_signature_to")" + declare -r signing_hash + + # encode the Safe Transaction Service API call + declare safe_multisig_transaction + safe_multisig_transaction="$( + jq -Mc \ + "$eip712_message_json_template"', + "contractTransactionHash": $signing_hash, + "sender": $sender, + "signature": $signature, + "origin": "0xSettlerCLI" + } + ' \ + --arg to "$_save_signature_to" \ + --arg data "$_save_signature_call" \ + --arg operation $_save_signature_operation \ + --arg nonce $(nonce) \ + --arg signing_hash "$signing_hash" \ + --arg sender "$signer" \ + --arg signature "$_save_signature_signature" \ + --arg safe_address "$safe_address" \ + <<<'{}' + )" + + # call the API + curl --fail "$safe_url"'/v1/safes/'"$safe_address"'/multisig-transactions/' -X POST -H 'Content-Type: application/json' --data "$safe_multisig_transaction" + + echo 'Signature submitted' >&2 + fi +} diff --git a/sh/confirm_new_settler.sh b/sh/confirm_new_settler.sh index d32658600..8341154fe 100755 --- a/sh/confirm_new_settler.sh +++ b/sh/confirm_new_settler.sh @@ -138,73 +138,10 @@ while (( ${#deploy_calldatas[@]} >= 2 )) ; do declare struct_json struct_json="$(eip712_json "$deploy_calldata" $operation)" - # sign the message declare signature - if [[ $wallet_type = 'frame' ]] ; then - declare typedDataRPC - typedDataRPC="$( - jq -Mc \ - ' - { - "jsonrpc": "2.0", - "method": "eth_signTypedData", - "params": [ - $signer, - . - ], - "id": 1 - } - ' \ - --arg signer "$signer" \ - <<<"$struct_json" - )" - signature="$(curl --fail -s -X POST --url 'http://127.0.0.1:1248' --data "$typedDataRPC")" - if [[ $signature = *error* ]] ; then - echo "$signature" >&2 - exit 1 - fi - signature="$(jq -Mr .result <<<"$signature")" - else - signature="$(cast wallet sign "${wallet_args[@]}" --from "$signer" --data "$struct_json")" - fi + signature="$(sign_call "$struct_json")" - if [[ $safe_url = 'NOT SUPPORTED' ]] ; then - declare signature_file - signature_file="$project_root"/settler_confirmation_"$chain_display_name"_"$(git rev-parse --short=8 HEAD)"_"$(tr '[:upper:]' '[:lower:]' <<<"$signer")"_$(nonce).txt - echo "$signature" >"$signature_file" - - echo "Signature saved to '$signature_file'" >&2 - else - declare signing_hash - signing_hash="$(eip712_hash "$deploy_calldata" $operation)" - - # encode the Safe Transaction Service API call - declare safe_multisig_transaction - safe_multisig_transaction="$( - jq -Mc \ - "$eip712_message_json_template"', - "contractTransactionHash": $signing_hash, - "sender": $sender, - "signature": $signature, - "origin": "0xSettlerCLI" - } - ' \ - --arg to "$(target $operation)" \ - --arg data "$deploy_calldata" \ - --arg operation $operation \ - --arg nonce $(nonce) \ - --arg signing_hash "$signing_hash" \ - --arg sender "$signer" \ - --arg signature "$signature" \ - --arg safe_address "$safe_address" \ - <<<'{}' - )" - - # call the API - curl --fail -s "$safe_url"'/v1/safes/'"$safe_address"'/multisig-transactions/' -X POST -H 'Content-Type: application/json' --data "$safe_multisig_transaction" - - echo 'Signature submitted' >&2 - fi + save_signature settler_confirmation "$deploy_calldata" "$signature" $operation SAFE_NONCE_INCREMENT=$((${SAFE_NONCE_INCREMENT:-0} + 1)) done diff --git a/sh/confirm_replace_signer.sh b/sh/confirm_replace_signer.sh new file mode 100755 index 000000000..b49345788 --- /dev/null +++ b/sh/confirm_replace_signer.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +## POSIX Bash implementation of realpath +## Copied and modified from https://github.com/mkropat/sh-realpath and https://github.com/AsymLabs/realpath-lib/ +## Copyright (c) 2014 Michael Kropat - MIT License +## Copyright (c) 2013 Asymmetry Laboratories - MIT License + +realpath() { + _resolve_symlinks "$(_canonicalize "$1")" +} + +_directory() { + local out slsh + slsh=/ + out="$1" + out="${out//$slsh$slsh/$slsh}" + if [ "$out" = / ]; then + echo / + return + fi + out="${out%/}" + case "$out" in + */*) + out="${out%/*}" + ;; + *) + out=. + ;; + esac + if [ "$out" ]; then + printf '%s\n' "$out" + else + echo / + fi +} + +_file() { + local out slsh + slsh=/ + out="$1" + out="${out//$slsh$slsh/$slsh}" + if [ "$out" = / ]; then + echo / + return + fi + out="${out%/}" + out="${out##*/}" + printf '%s\n' "$out" +} + +_resolve_symlinks() { + local path pattern context + while [ -L "$1" ]; do + context="$(_directory "$1")" + path="$(POSIXLY_CORRECT=y ls -ld -- "$1" 2>/dev/null)" + pattern='*'"$(_escape "$1")"' -> ' + path="${path#$pattern}" + set -- "$(_canonicalize "$(_prepend_context "$context" "$path")")" "$@" + _assert_no_path_cycles "$@" || return 1 + done + printf '%s\n' "$1" +} + +_escape() { + local out + out='' + local -i i + for ((i=0; i < ${#1}; i+=1)); do + out+='\'"${1:$i:1}" + done + printf '%s\n' "$out" +} + +_prepend_context() { + if [ "$1" = . ]; then + printf '%s\n' "$2" + else + case "$2" in + /* ) printf '%s\n' "$2" ;; + * ) printf '%s\n' "$1/$2" ;; + esac + fi +} + +_assert_no_path_cycles() { + local target path + + if [ $# -gt 16 ]; then + return 1 + fi + + target="$1" + shift + + for path in "$@"; do + if [ "$path" = "$target" ]; then + return 1 + fi + done +} + +_canonicalize() { + local d f + if [ -d "$1" ]; then + (CDPATH= cd -P "$1" 2>/dev/null && pwd -P) + else + d="$(_directory "$1")" + f="$(_file "$1")" + (CDPATH= cd -P "$d" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$f") + fi +} + +## end POSIX Bash implementation of realpath + +set -Eeufo pipefail -o posix + +declare project_root +project_root="$(_directory "$(_directory "$(realpath "${BASH_SOURCE[0]}")")")" +declare -r project_root +cd "$project_root" + +. "$project_root"/sh/common.sh + +declare safe_address +safe_address="$(get_config governance.deploymentSafe)" +declare -r safe_address + +. "$project_root"/sh/common_safe.sh +. "$project_root"/sh/common_safe_owner.sh +. "$project_root"/sh/common_wallet_type.sh + +declare old_owner +old_owner="$1" +shift +old_owner="$(cast to-checksum "$old_owner")" +declare -r old_owner + +declare new_owner +new_owner="$1" +shift +new_owner="$(cast to-checksum "$new_owner")" +declare -r new_owner + +declare -r swapOwner_sig='swapOwner(address,address,address)' +declare swapOwner_call +swapOwner_call="$(cast calldata "$swapOwner_sig" "$(prev_owner "$old_owner")" "$old_owner" "$new_owner")" +declare -r swapOwner_call + +declare struct_json +struct_json="$(eip712_json "$swapOwner_call" 0 "$safe_address")" +declare -r struct_json + +declare signature +signature="$(sign_call "$struct_json")" +declare -r signature + +save_signature replace_signer "$swapOwner_call" "$signature" 0 "$safe_address" diff --git a/sh/deploy_new_settler.sh b/sh/deploy_new_settler.sh index 0a427fb8a..92681e1e9 100755 --- a/sh/deploy_new_settler.sh +++ b/sh/deploy_new_settler.sh @@ -132,6 +132,7 @@ IFS='' read -p 'What address will you submit with?: ' -e -r -i 0xEf37aD2BACD7011 declare -r signer . "$project_root"/sh/common_wallet_type.sh +. "$project_root"/sh/common_safe_deployer.sh . "$project_root"/sh/common_deploy_settler.sh # set minimum gas price to (mostly for Arbitrum and BNB) @@ -158,38 +159,8 @@ while (( ${#deploy_calldatas[@]} >= 2 )) ; do declare signing_hash signing_hash="$(eip712_hash "$deploy_calldata" $operation)" - declare -a signatures=() - if [[ $safe_url = 'NOT SUPPORTED' ]] ; then - set +f - for confirmation in "$project_root"/settler_confirmation_"$chain_display_name"_"$(git rev-parse --short=8 HEAD)"_*_$(nonce).txt ; do - signatures+=("$(<"$confirmation")") - done - set -f - - if (( ${#signatures[@]} != 2 )) ; then - echo 'Bad number of signatures' >&2 - exit 1 - fi - else - declare signatures_json - signatures_json="$(curl --fail -s "$safe_url"'/v1/multisig-transactions/'"$signing_hash"'/confirmations/?executed=false' -X GET)" - - if (( $(jq -Mr .count <<<"$signatures_json") != 2 )) ; then - echo 'Bad number of signatures' >&2 - exit 1 - fi - - if [ "$(jq -Mr '.results[1].owner' <<<"$signatures_json" | tr '[:upper:]' '[:lower:]')" \< "$(jq -Mr '.results[0].owner' <<<"$signatures_json" | tr '[:upper:]' '[:lower:]')" ] ; then - signatures+=( "$(jq -Mr '.results[1].signature' <<<"$signatures_json")" ) - signatures+=( "$(jq -Mr '.results[0].signature' <<<"$signatures_json")" ) - else - signatures+=( "$(jq -Mr '.results[0].signature' <<<"$signatures_json")" ) - signatures+=( "$(jq -Mr '.results[1].signature' <<<"$signatures_json")" ) - fi - fi - declare packed_signatures - packed_signatures="$(cast concat-hex "${signatures[@]}")" + packed_signatures="$(retrieve_signatures settler_confirmation "$deploy_calldata" $operation)" # configure gas limit declare -a args=( diff --git a/sh/replace_signer.sh b/sh/replace_signer.sh new file mode 100755 index 000000000..1cd5e3de0 --- /dev/null +++ b/sh/replace_signer.sh @@ -0,0 +1,195 @@ +#!/bin/bash + +## POSIX Bash implementation of realpath +## Copied and modified from https://github.com/mkropat/sh-realpath and https://github.com/AsymLabs/realpath-lib/ +## Copyright (c) 2014 Michael Kropat - MIT License +## Copyright (c) 2013 Asymmetry Laboratories - MIT License + +realpath() { + _resolve_symlinks "$(_canonicalize "$1")" +} + +_directory() { + local out slsh + slsh=/ + out="$1" + out="${out//$slsh$slsh/$slsh}" + if [ "$out" = / ]; then + echo / + return + fi + out="${out%/}" + case "$out" in + */*) + out="${out%/*}" + ;; + *) + out=. + ;; + esac + if [ "$out" ]; then + printf '%s\n' "$out" + else + echo / + fi +} + +_file() { + local out slsh + slsh=/ + out="$1" + out="${out//$slsh$slsh/$slsh}" + if [ "$out" = / ]; then + echo / + return + fi + out="${out%/}" + out="${out##*/}" + printf '%s\n' "$out" +} + +_resolve_symlinks() { + local path pattern context + while [ -L "$1" ]; do + context="$(_directory "$1")" + path="$(POSIXLY_CORRECT=y ls -ld -- "$1" 2>/dev/null)" + pattern='*'"$(_escape "$1")"' -> ' + path="${path#$pattern}" + set -- "$(_canonicalize "$(_prepend_context "$context" "$path")")" "$@" + _assert_no_path_cycles "$@" || return 1 + done + printf '%s\n' "$1" +} + +_escape() { + local out + out='' + local -i i + for ((i=0; i < ${#1}; i+=1)); do + out+='\'"${1:$i:1}" + done + printf '%s\n' "$out" +} + +_prepend_context() { + if [ "$1" = . ]; then + printf '%s\n' "$2" + else + case "$2" in + /* ) printf '%s\n' "$2" ;; + * ) printf '%s\n' "$1/$2" ;; + esac + fi +} + +_assert_no_path_cycles() { + local target path + + if [ $# -gt 16 ]; then + return 1 + fi + + target="$1" + shift + + for path in "$@"; do + if [ "$path" = "$target" ]; then + return 1 + fi + done +} + +_canonicalize() { + local d f + if [ -d "$1" ]; then + (CDPATH= cd -P "$1" 2>/dev/null && pwd -P) + else + d="$(_directory "$1")" + f="$(_file "$1")" + (CDPATH= cd -P "$d" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$f") + fi +} + +## end POSIX Bash implementation of realpath + +set -Eeufo pipefail -o posix + +declare project_root +project_root="$(_directory "$(_directory "$(realpath "${BASH_SOURCE[0]}")")")" +declare -r project_root +cd "$project_root" + +. "$project_root"/sh/common.sh + +declare safe_address +safe_address="$(get_config governance.deploymentSafe)" +declare -r safe_address + +. "$project_root"/sh/common_safe.sh + +declare signer +IFS='' read -p 'What address will you submit with?: ' -e -r -i 0xEf37aD2BACD70119F141140f7B5E46Cd53a65fc4 signer +declare -r signer + +. "$project_root"/sh/common_safe_deployer.sh +. "$project_root"/sh/common_wallet_type.sh + +declare old_owner +old_owner="$1" +shift +old_owner="$(cast to-checksum "$old_owner")" +declare -r old_owner + +declare new_owner +new_owner="$1" +shift +new_owner="$(cast to-checksum "$new_owner")" +declare -r new_owner + +declare -r swapOwner_sig='swapOwner(address,address,address)' +declare swapOwner_call +swapOwner_call="$(cast calldata "$swapOwner_sig" "$(prev_owner "$old_owner")" "$old_owner" "$new_owner")" +declare -r swapOwner_call + +# set minimum gas price to (mostly for Arbitrum and BNB) +declare -i min_gas_price +min_gas_price="$(get_config minGasPriceGwei)" +min_gas_price=$((min_gas_price * 1000000000)) +declare -r -i min_gas_price +declare -i gas_price +gas_price="$(cast gas-price --rpc-url "$rpc_url")" +if (( gas_price < min_gas_price )) ; then + echo 'Setting gas price to minimum of '$((min_gas_price / 1000000000))' gwei' >&2 + gas_price=$min_gas_price +fi +declare -r -i gas_price +declare -i gas_estimate_multiplier +gas_estimate_multiplier="$(get_config gasMultiplierPercent)" +declare -r -i gas_estimate_multiplier + +declare signing_hash +signing_hash="$(eip712_hash "$swapOwner_call" 0 "$safe_address")" +declare -r signing_hash + +declare packed_signatures +packed_signatures="$(retrieve_signatures replace_signer "$swapOwner_call" 0 "$safe_address")" +declare -r packed_signatures + +# configure gas limit +declare -r -a args=( + "$safe_address" "$execTransaction_sig" + # to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, signatures + "$safe_address" 0 "$swapOwner_call" 0 0 0 0 "$(cast address-zero)" "$(cast address-zero)" "$packed_signatures" +) + +# set gas limit and add multiplier/headroom (again mostly for Arbitrum) +declare -i gas_limit +gas_limit="$(cast estimate --from "$signer" --rpc-url "$rpc_url" --gas-price $gas_price --chain $chainid "${args[@]}")" +gas_limit=$((gas_limit * gas_estimate_multiplier / 100)) +declare -r -i gas_limit + +if [[ $wallet_type = 'frame' ]] ; then + cast send --confirmations 10 --from "$signer" --rpc-url 'http://127.0.0.1:1248/' --chain $chainid --gas-price $gas_price --gas-limit $gas_limit "${wallet_args[@]}" $(get_config extraFlags) "${args[@]}" +else + cast send --confirmations 10 --from "$signer" --rpc-url "$rpc_url" --chain $chainid --gas-price $gas_price --gas-limit $gas_limit "${wallet_args[@]}" $(get_config extraFlags) "${args[@]}" +fi diff --git a/src/SettlerBase.sol b/src/SettlerBase.sol index cf207547e..5237ece05 100644 --- a/src/SettlerBase.sol +++ b/src/SettlerBase.sol @@ -5,6 +5,8 @@ import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {IERC721Owner} from "./IERC721Owner.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {DEPLOYER} from "./deployer/DeployerAddress.sol"; + import {Basic} from "./core/Basic.sol"; import {RfqOrderSettlement} from "./core/RfqOrderSettlement.sol"; import {UniswapV3Fork} from "./core/UniswapV3Fork.sol"; @@ -63,7 +65,7 @@ abstract contract SettlerBase is Basic, RfqOrderSettlement, UniswapV3Fork, Unisw constructor(bytes20 gitCommit) { if (block.chainid != 31337) { emit GitCommit(gitCommit); - assert(IERC721Owner(0x00000000000004533Fe15556B1E086BB1A72cEae).ownerOf(_tokenId()) == address(this)); + assert(IERC721Owner(DEPLOYER).ownerOf(_tokenId()) == address(this)); } else { assert(gitCommit == bytes20(0)); } diff --git a/src/chains/Blast/Common.sol b/src/chains/Blast/Common.sol index 8654c4690..e0e052cd0 100644 --- a/src/chains/Blast/Common.sol +++ b/src/chains/Blast/Common.sol @@ -37,6 +37,7 @@ import { rogueXV1Factory, rogueXV1InitHash, rogueXV1ForkId, IRoxSpotSwapCallback } from "../../core/univ3forks/RogueXV1.sol"; +import {DEPLOYER} from "../../deployer/DeployerAddress.sol"; import {IOwnable} from "../../deployer/TwoStepOwnable.sol"; import {BLAST, BLAST_USDB, BLAST_WETH, BlastYieldMode, BlastGasMode} from "./IBlast.sol"; @@ -47,11 +48,7 @@ abstract contract BlastMixin is FreeMemory, SettlerBase { constructor() { if (block.chainid != 31337) { assert(block.chainid == 81457); - BLAST.configure( - BlastYieldMode.AUTOMATIC, - BlastGasMode.CLAIMABLE, - IOwnable(0x00000000000004533Fe15556B1E086BB1A72cEae).owner() - ); + BLAST.configure(BlastYieldMode.AUTOMATIC, BlastGasMode.CLAIMABLE, IOwnable(DEPLOYER).owner()); BLAST_USDB.configure(BlastYieldMode.VOID); BLAST_WETH.configure(BlastYieldMode.VOID); } diff --git a/src/chains/Ink/Common.sol b/src/chains/Ink/Common.sol new file mode 100644 index 000000000..5cdcaf7e1 --- /dev/null +++ b/src/chains/Ink/Common.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.25; + +import {SettlerBase} from "../../SettlerBase.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {FreeMemory} from "../../utils/FreeMemory.sol"; + +import {ISettlerActions} from "../../ISettlerActions.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {UnknownForkId} from "../../core/SettlerErrors.sol"; + +import { + uniswapV3InkFactory, + uniswapV3InitHash, + uniswapV3ForkId, + IUniswapV3Callback +} from "../../core/univ3forks/UniswapV3.sol"; + +// Solidity inheritance is stupid +import {SettlerAbstract} from "../../SettlerAbstract.sol"; + +abstract contract InkMixin is FreeMemory, SettlerBase { + constructor() { + assert(block.chainid == 57073 || block.chainid == 31337); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + virtual + override( /* SettlerAbstract, */ SettlerBase) + DANGEROUS_freeMemory + returns (bool) + { + if (super._dispatch(i, action, data)) { + return true; + } else { + return false; + } + return true; + } + + function _uniV3ForkInfo(uint8 forkId) + internal + pure + override + returns (address factory, bytes32 initHash, uint32 callbackSelector) + { + if (forkId == uniswapV3ForkId) { + factory = uniswapV3InkFactory; + initHash = uniswapV3InitHash; + callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); + } else { + revert UnknownForkId(forkId); + } + } +} diff --git a/src/chains/Ink/Intent.sol b/src/chains/Ink/Intent.sol new file mode 100644 index 000000000..2bd1ac9d6 --- /dev/null +++ b/src/chains/Ink/Intent.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.25; + +import {InkSettlerMetaTxn} from "./MetaTxn.sol"; +import {SettlerIntent} from "../../SettlerIntent.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {ISettlerActions} from "../../ISettlerActions.sol"; + +// Solidity inheritance is stupid +import {SettlerAbstract} from "../../SettlerAbstract.sol"; +import {SettlerBase} from "../../SettlerBase.sol"; +import {SettlerMetaTxn} from "../../SettlerMetaTxn.sol"; +import {SettlerIntent} from "../../SettlerIntent.sol"; +import {AbstractContext} from "../../Context.sol"; +import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; +import {Permit2PaymentMetaTxn} from "../../core/Permit2Payment.sol"; + +/// @custom:security-contact security@0x.org +contract InkSettlerIntent is SettlerIntent, InkSettlerMetaTxn { + constructor(bytes20 gitCommit) InkSettlerMetaTxn(gitCommit) {} + + // Solidity inheritance is stupid + function executeMetaTxn( + AllowedSlippage calldata slippage, + bytes[] calldata actions, + bytes32, /* zid & affiliate */ + address msgSender, + bytes calldata sig + ) public override(SettlerIntent, SettlerMetaTxn) returns (bool) { + return super.executeMetaTxn(slippage, actions, bytes32(0), msgSender, sig); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + override(InkSettlerMetaTxn, SettlerBase, SettlerAbstract) + returns (bool) + { + return super._dispatch(i, action, data); + } + + function _msgSender() internal view override(SettlerIntent, InkSettlerMetaTxn) returns (address) { + return super._msgSender(); + } + + function _witnessTypeSuffix() + internal + pure + override(SettlerIntent, Permit2PaymentMetaTxn) + returns (string memory) + { + return super._witnessTypeSuffix(); + } + + function _tokenId() internal pure override(SettlerIntent, SettlerMetaTxn, SettlerAbstract) returns (uint256) { + return super._tokenId(); + } + + function _dispatchVIP(uint256 action, bytes calldata data, bytes calldata sig) + internal + override(InkSettlerMetaTxn, SettlerMetaTxn) + returns (bool) + { + return super._dispatchVIP(action, data, sig); + } + + function _permitToSellAmount(ISignatureTransfer.PermitTransferFrom memory permit) + internal + pure + override(SettlerIntent, Permit2PaymentAbstract, Permit2PaymentMetaTxn) + returns (uint256) + { + return super._permitToSellAmount(permit); + } +} diff --git a/src/chains/Ink/MetaTxn.sol b/src/chains/Ink/MetaTxn.sol new file mode 100644 index 000000000..73cfe078a --- /dev/null +++ b/src/chains/Ink/MetaTxn.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.25; + +import {InkMixin} from "./Common.sol"; +import {SettlerMetaTxn} from "../../SettlerMetaTxn.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {ISettlerActions} from "../../ISettlerActions.sol"; + +// Solidity inheritance is stupid +import {SettlerAbstract} from "../../SettlerAbstract.sol"; +import {SettlerBase} from "../../SettlerBase.sol"; +import {AbstractContext} from "../../Context.sol"; + +/// @custom:security-contact security@0x.org +contract InkSettlerMetaTxn is SettlerMetaTxn, InkMixin { + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} + + function _dispatchVIP(uint256 action, bytes calldata data, bytes calldata sig) + internal + virtual + override + DANGEROUS_freeMemory + returns (bool) + { + if (super._dispatchVIP(action, data, sig)) { + return true; + } else { + return false; + } + return true; + } + + // Solidity inheritance is stupid + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + virtual + override(SettlerAbstract, SettlerBase, InkMixin) + returns (bool) + { + return super._dispatch(i, action, data); + } + + function _msgSender() internal view virtual override(SettlerMetaTxn, AbstractContext) returns (address) { + return super._msgSender(); + } +} diff --git a/src/chains/Ink/TakerSubmitted.sol b/src/chains/Ink/TakerSubmitted.sol new file mode 100644 index 000000000..713b8e69c --- /dev/null +++ b/src/chains/Ink/TakerSubmitted.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.25; + +import {InkMixin} from "./Common.sol"; +import {Settler} from "../../Settler.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {ISettlerActions} from "../../ISettlerActions.sol"; + +// Solidity inheritance is stupid +import {SettlerAbstract} from "../../SettlerAbstract.sol"; +import {SettlerBase} from "../../SettlerBase.sol"; +import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; +import {AbstractContext} from "../../Context.sol"; + +/// @custom:security-contact security@0x.org +contract InkSettler is Settler, InkMixin { + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} + + function _dispatchVIP(uint256 action, bytes calldata data) internal override DANGEROUS_freeMemory returns (bool) { + if (super._dispatchVIP(action, data)) { + return true; + } else { + return false; + } + return true; + } + + // Solidity inheritance is stupid + function _isRestrictedTarget(address target) + internal + pure + override(Settler, Permit2PaymentAbstract) + returns (bool) + { + return super._isRestrictedTarget(target); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + override(SettlerAbstract, SettlerBase, InkMixin) + returns (bool) + { + return super._dispatch(i, action, data); + } + + function _msgSender() internal view override(Settler, AbstractContext) returns (address) { + return super._msgSender(); + } +} diff --git a/src/chains/Mainnet/Common.sol b/src/chains/Mainnet/Common.sol index 147cae55c..9ec8f1769 100644 --- a/src/chains/Mainnet/Common.sol +++ b/src/chains/Mainnet/Common.sol @@ -36,6 +36,9 @@ import { ISolidlyV3Callback } from "../../core/univ3forks/SolidlyV3.sol"; +import {DEPLOYER} from "../../deployer/DeployerAddress.sol"; +import {IOwnable} from "../../deployer/TwoStepOwnable.sol"; + // Solidity inheritance is stupid import {SettlerAbstract} from "../../SettlerAbstract.sol"; @@ -137,4 +140,8 @@ abstract contract MainnetMixin is function _curveFactory() internal pure override returns (address) { return 0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963; } + + function rebateClaimer() external view returns (address) { + return IOwnable(DEPLOYER).owner(); + } } diff --git a/src/chains/Mode/Common.sol b/src/chains/Mode/Common.sol index 2ee850fbc..b13c1efa8 100644 --- a/src/chains/Mode/Common.sol +++ b/src/chains/Mode/Common.sol @@ -19,6 +19,7 @@ import {IAlgebraCallback} from "../../core/univ3forks/Algebra.sol"; import {swapModeV3Factory, swapModeV3InitHash, swapModeV3ForkId} from "../../core/univ3forks/SwapModeV3.sol"; import {IUniswapV3Callback} from "../../core/univ3forks/UniswapV3.sol"; +import {DEPLOYER} from "../../deployer/DeployerAddress.sol"; import {MODE_SFS} from "./IModeSFS.sol"; // Solidity inheritance is stupid @@ -27,7 +28,7 @@ import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; abstract contract ModeMixin is FreeMemory, SettlerBase { constructor() { assert(block.chainid == 34443 || block.chainid == 31337); - MODE_SFS.assign(MODE_SFS.getTokenId(0x00000000000004533Fe15556B1E086BB1A72cEae)); + MODE_SFS.assign(MODE_SFS.getTokenId(DEPLOYER)); } function _isRestrictedTarget(address target) diff --git a/src/core/univ3forks/UniswapV3.sol b/src/core/univ3forks/UniswapV3.sol index 2fb3d4545..1946957c6 100644 --- a/src/core/univ3forks/UniswapV3.sol +++ b/src/core/univ3forks/UniswapV3.sol @@ -14,6 +14,7 @@ address constant uniswapV3TaikoFactory = 0x75FC67473A91335B5b8F8821277262a13B38c address constant uniswapV3WorldChainFactory = 0x7a5028BDa40e7B173C278C5342087826455ea25a; address constant uniswapV3GnosisFactory = 0xe32F7dD7e3f098D518ff19A22d5f028e076489B1; address constant uniswapV3SonicFactory = 0xcb2436774C3e191c85056d248EF4260ce5f27A9D; +address constant uniswapV3InkFactory = 0x640887A9ba3A9C53Ed27D0F7e8246A4F933f3424; bytes32 constant uniswapV3InitHash = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; uint8 constant uniswapV3ForkId = 0; diff --git a/src/deployer/BlastDeployer.sol b/src/deployer/BlastDeployer.sol index 4e31a071f..feb80e99a 100644 --- a/src/deployer/BlastDeployer.sol +++ b/src/deployer/BlastDeployer.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity =0.8.25; +import {DEPLOYER} from "./DeployerAddress.sol"; import {Deployer} from "./Deployer.sol"; import {BLAST, BlastYieldMode, BlastGasMode} from "../chains/Blast/IBlast.sol"; @@ -8,11 +9,7 @@ import {BLAST, BlastYieldMode, BlastGasMode} from "../chains/Blast/IBlast.sol"; contract BlastDeployer is Deployer { constructor(uint256 version) Deployer(version) { assert(block.chainid == 81457); - BLAST.configure( - BlastYieldMode.AUTOMATIC, - BlastGasMode.CLAIMABLE, - BlastDeployer(0x00000000000004533Fe15556B1E086BB1A72cEae).owner() - ); + BLAST.configure(BlastYieldMode.AUTOMATIC, BlastGasMode.CLAIMABLE, BlastDeployer(DEPLOYER).owner()); } function initialize(address initialOwner) public override { diff --git a/src/deployer/Deployer.sol b/src/deployer/Deployer.sol index 2965636cc..73037f062 100644 --- a/src/deployer/Deployer.sol +++ b/src/deployer/Deployer.sol @@ -15,6 +15,7 @@ import {ProxyMultiCall} from "../utils/ProxyMultiCall.sol"; import {Feature, wrap, isNull} from "./Feature.sol"; import {Nonce, zero, isNull} from "./Nonce.sol"; import {IDeployer, IERC721ViewMetadata} from "./IDeployer.sol"; +import {DEPLOYER} from "./DeployerAddress.sol"; library NonceList { struct ListElem { @@ -149,7 +150,7 @@ contract Deployer is IDeployer, ERC1967UUPSUpgradeable, Context, ERC1967TwoStepO } function initialize(address initialOwner) public virtual { - require(address(this) == 0x00000000000004533Fe15556B1E086BB1A72cEae || block.chainid == 31337); + require(address(this) == DEPLOYER || block.chainid == 31337); if (_implVersion == 1) { _setPendingOwner(initialOwner); } else { diff --git a/src/deployer/DeployerAddress.sol b/src/deployer/DeployerAddress.sol new file mode 100644 index 000000000..1cb28fa2f --- /dev/null +++ b/src/deployer/DeployerAddress.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +address constant DEPLOYER = 0x00000000000004533Fe15556B1E086BB1A72cEae; diff --git a/src/deployer/ModeDeployer.sol b/src/deployer/ModeDeployer.sol index d2760022d..1b1893e30 100644 --- a/src/deployer/ModeDeployer.sol +++ b/src/deployer/ModeDeployer.sol @@ -2,6 +2,7 @@ pragma solidity =0.8.25; import {Deployer} from "./Deployer.sol"; +import {DEPLOYER} from "./DeployerAddress.sol"; import {MODE_SFS} from "../chains/Mode/IModeSFS.sol"; /// @custom:security-contact security@0x.org @@ -10,11 +11,11 @@ contract ModeDeployer is Deployer { constructor(uint256 version) Deployer(version) { assert(block.chainid == 34443); - if (0x00000000000004533Fe15556B1E086BB1A72cEae.code.length == 0) { + if (DEPLOYER.code.length == 0) { assert(_implVersion == 1); sfsTokenId = MODE_SFS.register(0xf36b9f50E59870A24F42F9Ba43b2aD0A4b8f2F51); } else { - MODE_SFS.assign(sfsTokenId = MODE_SFS.getTokenId(0x00000000000004533Fe15556B1E086BB1A72cEae)); + MODE_SFS.assign(sfsTokenId = MODE_SFS.getTokenId(DEPLOYER)); } } diff --git a/src/deployer/SafeModule.sol b/src/deployer/SafeModule.sol index eed32ffaf..a5172faec 100644 --- a/src/deployer/SafeModule.sol +++ b/src/deployer/SafeModule.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; +import {DEPLOYER} from "./DeployerAddress.sol"; import {IDeployer, IDeployerRemove} from "./IDeployer.sol"; import {Feature} from "./Feature.sol"; import {Nonce} from "./Nonce.sol"; @@ -23,7 +24,7 @@ contract ZeroExSettlerDeployerSafeModule is IDeployerRemove { using Revert for bool; ISafeMinimal public immutable safe; - IDeployer public constant deployer = IDeployer(0x00000000000004533Fe15556B1E086BB1A72cEae); + IDeployer public constant deployer = IDeployer(DEPLOYER); constructor(address _safe) { assert(address(this) == 0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30 || block.chainid == 31337); diff --git a/test/deployer/Deployer.t.sol b/test/deployer/Deployer.t.sol index c36772bfa..fbb22fe6f 100644 --- a/test/deployer/Deployer.t.sol +++ b/test/deployer/Deployer.t.sol @@ -7,6 +7,7 @@ import {ERC1967UUPSProxy} from "src/proxy/ERC1967UUPSProxy.sol"; import {AddressDerivation} from "src/utils/AddressDerivation.sol"; import {Create3} from "src/utils/Create3.sol"; import {IERC1967Proxy} from "src/proxy/ERC1967UUPSUpgradeable.sol"; +import {DEPLOYER} from "src/deployer/DeployerAddress.sol"; import "@forge-std/Test.sol"; @@ -19,7 +20,7 @@ contract DeployerTest is Test { function setUp() public { vm.createSelectFork(vm.envString("MAINNET_RPC_URL"), 19921675); - deployer = Deployer(0x00000000000004533Fe15556B1E086BB1A72cEae); + deployer = Deployer(DEPLOYER); vm.label(address(deployer), "Deployer (proxy)"); vm.prank(deployer.owner());