@@ -516,6 +516,24 @@ impl CallTraceDecoder {
516516 Some ( decoded. iter ( ) . map ( format_token) . collect ( ) )
517517 }
518518 }
519+ "createFork" |
520+ "createSelectFork" |
521+ "rpc" => {
522+ let mut decoded = func. abi_decode_input ( & data[ SELECTOR_LEN ..] , false ) . ok ( ) ?;
523+
524+ // Redact RPC URL except if referenced by an alias
525+ if !decoded. is_empty ( ) && func. inputs [ 0 ] . ty == "string" {
526+ let url_or_alias = decoded[ 0 ] . as_str ( ) . unwrap_or_default ( ) ;
527+
528+ if url_or_alias. starts_with ( "http" ) || url_or_alias. starts_with ( "ws" ) {
529+ decoded[ 0 ] = DynSolValue :: String ( "<rpc url>" . to_string ( ) ) ;
530+ }
531+ } else {
532+ return None ;
533+ }
534+
535+ Some ( decoded. iter ( ) . map ( format_token) . collect ( ) )
536+ }
519537 _ => None ,
520538 }
521539 }
@@ -558,6 +576,7 @@ impl CallTraceDecoder {
558576 "promptSecret" | "promptSecretUint" => Some ( "<secret>" ) ,
559577 "parseJson" if self . verbosity < 5 => Some ( "<encoded JSON value>" ) ,
560578 "readFile" if self . verbosity < 5 => Some ( "<file>" ) ,
579+ "rpcUrl" | "rpcUrls" | "rpcUrlStructs" => Some ( "<rpc url>" ) ,
561580 _ => None ,
562581 }
563582 . map ( Into :: into)
@@ -670,7 +689,7 @@ mod tests {
670689 use alloy_primitives:: hex;
671690
672691 #[ test]
673- fn test_should_redact_pk ( ) {
692+ fn test_should_redact ( ) {
674693 let decoder = CallTraceDecoder :: new ( ) ;
675694
676695 // [function_signature, data, expected]
@@ -726,13 +745,286 @@ mod tests {
726745 . to_string( ) ,
727746 ] ) ,
728747 ) ,
748+ (
749+ // cast calldata "createFork(string)" "https://eth-mainnet.g.alchemy.com/v2/api_key"
750+ "createFork(string)" ,
751+ hex!(
752+ "
753+ 31ba3498
754+ 0000000000000000000000000000000000000000000000000000000000000020
755+ 000000000000000000000000000000000000000000000000000000000000002c
756+ 68747470733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f
757+ 6d2f76322f6170695f6b65790000000000000000000000000000000000000000
758+ "
759+ )
760+ . to_vec( ) ,
761+ Some ( vec![ "\" <rpc url>\" " . to_string( ) ] ) ,
762+ ) ,
763+ (
764+ // cast calldata "createFork(string)" "wss://eth-mainnet.g.alchemy.com/v2/api_key"
765+ "createFork(string)" ,
766+ hex!(
767+ "
768+ 31ba3498
769+ 0000000000000000000000000000000000000000000000000000000000000020
770+ 000000000000000000000000000000000000000000000000000000000000002a
771+ 7773733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f6d2f
772+ 76322f6170695f6b657900000000000000000000000000000000000000000000
773+ "
774+ )
775+ . to_vec( ) ,
776+ Some ( vec![ "\" <rpc url>\" " . to_string( ) ] ) ,
777+ ) ,
778+ (
779+ // cast calldata "createFork(string)" "mainnet"
780+ "createFork(string)" ,
781+ hex!(
782+ "
783+ 31ba3498
784+ 0000000000000000000000000000000000000000000000000000000000000020
785+ 0000000000000000000000000000000000000000000000000000000000000007
786+ 6d61696e6e657400000000000000000000000000000000000000000000000000
787+ "
788+ )
789+ . to_vec( ) ,
790+ Some ( vec![ "\" mainnet\" " . to_string( ) ] ) ,
791+ ) ,
792+ (
793+ // cast calldata "createFork(string,uint256)" "https://eth-mainnet.g.alchemy.com/v2/api_key" 1
794+ "createFork(string,uint256)" ,
795+ hex!(
796+ "
797+ 6ba3ba2b
798+ 0000000000000000000000000000000000000000000000000000000000000040
799+ 0000000000000000000000000000000000000000000000000000000000000001
800+ 000000000000000000000000000000000000000000000000000000000000002c
801+ 68747470733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f
802+ 6d2f76322f6170695f6b65790000000000000000000000000000000000000000
803+ "
804+ )
805+ . to_vec( ) ,
806+ Some ( vec![ "\" <rpc url>\" " . to_string( ) , "1" . to_string( ) ] ) ,
807+ ) ,
808+ (
809+ // cast calldata "createFork(string,uint256)" "mainnet" 1
810+ "createFork(string,uint256)" ,
811+ hex!(
812+ "
813+ 6ba3ba2b
814+ 0000000000000000000000000000000000000000000000000000000000000040
815+ 0000000000000000000000000000000000000000000000000000000000000001
816+ 0000000000000000000000000000000000000000000000000000000000000007
817+ 6d61696e6e657400000000000000000000000000000000000000000000000000
818+ "
819+ )
820+ . to_vec( ) ,
821+ Some ( vec![ "\" mainnet\" " . to_string( ) , "1" . to_string( ) ] ) ,
822+ ) ,
823+ (
824+ // cast calldata "createFork(string,bytes32)" "https://eth-mainnet.g.alchemy.com/v2/api_key" 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
825+ "createFork(string,bytes32)" ,
826+ hex!(
827+ "
828+ 7ca29682
829+ 0000000000000000000000000000000000000000000000000000000000000040
830+ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
831+ 000000000000000000000000000000000000000000000000000000000000002c
832+ 68747470733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f
833+ 6d2f76322f6170695f6b65790000000000000000000000000000000000000000
834+ "
835+ )
836+ . to_vec( ) ,
837+ Some ( vec![
838+ "\" <rpc url>\" " . to_string( ) ,
839+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
840+ . to_string( ) ,
841+ ] ) ,
842+ ) ,
843+ (
844+ // cast calldata "createFork(string,bytes32)" "mainnet"
845+ // 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
846+ "createFork(string,bytes32)" ,
847+ hex!(
848+ "
849+ 7ca29682
850+ 0000000000000000000000000000000000000000000000000000000000000040
851+ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
852+ 0000000000000000000000000000000000000000000000000000000000000007
853+ 6d61696e6e657400000000000000000000000000000000000000000000000000
854+ "
855+ )
856+ . to_vec( ) ,
857+ Some ( vec![
858+ "\" mainnet\" " . to_string( ) ,
859+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
860+ . to_string( ) ,
861+ ] ) ,
862+ ) ,
863+ (
864+ // cast calldata "createSelectFork(string)" "https://eth-mainnet.g.alchemy.com/v2/api_key"
865+ "createSelectFork(string)" ,
866+ hex!(
867+ "
868+ 98680034
869+ 0000000000000000000000000000000000000000000000000000000000000020
870+ 000000000000000000000000000000000000000000000000000000000000002c
871+ 68747470733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f
872+ 6d2f76322f6170695f6b65790000000000000000000000000000000000000000
873+ "
874+ )
875+ . to_vec( ) ,
876+ Some ( vec![ "\" <rpc url>\" " . to_string( ) ] ) ,
877+ ) ,
878+ (
879+ // cast calldata "createSelectFork(string)" "mainnet"
880+ "createSelectFork(string)" ,
881+ hex!(
882+ "
883+ 98680034
884+ 0000000000000000000000000000000000000000000000000000000000000020
885+ 0000000000000000000000000000000000000000000000000000000000000007
886+ 6d61696e6e657400000000000000000000000000000000000000000000000000
887+ "
888+ )
889+ . to_vec( ) ,
890+ Some ( vec![ "\" mainnet\" " . to_string( ) ] ) ,
891+ ) ,
892+ (
893+ // cast calldata "createSelectFork(string,uint256)" "https://eth-mainnet.g.alchemy.com/v2/api_key" 1
894+ "createSelectFork(string,uint256)" ,
895+ hex!(
896+ "
897+ 71ee464d
898+ 0000000000000000000000000000000000000000000000000000000000000040
899+ 0000000000000000000000000000000000000000000000000000000000000001
900+ 000000000000000000000000000000000000000000000000000000000000002c
901+ 68747470733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f
902+ 6d2f76322f6170695f6b65790000000000000000000000000000000000000000
903+ "
904+ )
905+ . to_vec( ) ,
906+ Some ( vec![ "\" <rpc url>\" " . to_string( ) , "1" . to_string( ) ] ) ,
907+ ) ,
908+ (
909+ // cast calldata "createSelectFork(string,uint256)" "mainnet" 1
910+ "createSelectFork(string,uint256)" ,
911+ hex!(
912+ "
913+ 71ee464d
914+ 0000000000000000000000000000000000000000000000000000000000000040
915+ 0000000000000000000000000000000000000000000000000000000000000001
916+ 0000000000000000000000000000000000000000000000000000000000000007
917+ 6d61696e6e657400000000000000000000000000000000000000000000000000
918+ "
919+ )
920+ . to_vec( ) ,
921+ Some ( vec![ "\" mainnet\" " . to_string( ) , "1" . to_string( ) ] ) ,
922+ ) ,
923+ (
924+ // cast calldata "createSelectFork(string,bytes32)" "https://eth-mainnet.g.alchemy.com/v2/api_key" 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
925+ "createSelectFork(string,bytes32)" ,
926+ hex!(
927+ "
928+ 84d52b7a
929+ 0000000000000000000000000000000000000000000000000000000000000040
930+ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
931+ 000000000000000000000000000000000000000000000000000000000000002c
932+ 68747470733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f
933+ 6d2f76322f6170695f6b65790000000000000000000000000000000000000000
934+ "
935+ )
936+ . to_vec( ) ,
937+ Some ( vec![
938+ "\" <rpc url>\" " . to_string( ) ,
939+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
940+ . to_string( ) ,
941+ ] ) ,
942+ ) ,
943+ (
944+ // cast calldata "createSelectFork(string,bytes32)" "mainnet"
945+ // 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
946+ "createSelectFork(string,bytes32)" ,
947+ hex!(
948+ "
949+ 84d52b7a
950+ 0000000000000000000000000000000000000000000000000000000000000040
951+ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
952+ 0000000000000000000000000000000000000000000000000000000000000007
953+ 6d61696e6e657400000000000000000000000000000000000000000000000000
954+ "
955+ )
956+ . to_vec( ) ,
957+ Some ( vec![
958+ "\" mainnet\" " . to_string( ) ,
959+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
960+ . to_string( ) ,
961+ ] ) ,
962+ ) ,
963+ (
964+ // cast calldata "rpc(string,string,string)" "https://eth-mainnet.g.alchemy.com/v2/api_key" "eth_getBalance" "[\"0x551e7784778ef8e048e495df49f2614f84a4f1dc\",\"0x0\"]"
965+ "rpc(string,string,string)" ,
966+ hex!(
967+ "
968+ 0199a220
969+ 0000000000000000000000000000000000000000000000000000000000000060
970+ 00000000000000000000000000000000000000000000000000000000000000c0
971+ 0000000000000000000000000000000000000000000000000000000000000100
972+ 000000000000000000000000000000000000000000000000000000000000002c
973+ 68747470733a2f2f6574682d6d61696e6e65742e672e616c6368656d792e636f
974+ 6d2f76322f6170695f6b65790000000000000000000000000000000000000000
975+ 000000000000000000000000000000000000000000000000000000000000000e
976+ 6574685f67657442616c616e6365000000000000000000000000000000000000
977+ 0000000000000000000000000000000000000000000000000000000000000034
978+ 5b22307835353165373738343737386566386530343865343935646634396632
979+ 363134663834613466316463222c22307830225d000000000000000000000000
980+ "
981+ )
982+ . to_vec( ) ,
983+ Some ( vec![
984+ "\" <rpc url>\" " . to_string( ) ,
985+ "\" eth_getBalance\" " . to_string( ) ,
986+ "\" [\\ \" 0x551e7784778ef8e048e495df49f2614f84a4f1dc\\ \" ,\\ \" 0x0\\ \" ]\" "
987+ . to_string( ) ,
988+ ] ) ,
989+ ) ,
990+ (
991+ // cast calldata "rpc(string,string,string)" "mainnet" "eth_getBalance"
992+ // "[\"0x551e7784778ef8e048e495df49f2614f84a4f1dc\",\"0x0\"]"
993+ "rpc(string,string,string)" ,
994+ hex!(
995+ "
996+ 0199a220
997+ 0000000000000000000000000000000000000000000000000000000000000060
998+ 00000000000000000000000000000000000000000000000000000000000000a0
999+ 00000000000000000000000000000000000000000000000000000000000000e0
1000+ 0000000000000000000000000000000000000000000000000000000000000007
1001+ 6d61696e6e657400000000000000000000000000000000000000000000000000
1002+ 000000000000000000000000000000000000000000000000000000000000000e
1003+ 6574685f67657442616c616e6365000000000000000000000000000000000000
1004+ 0000000000000000000000000000000000000000000000000000000000000034
1005+ 5b22307835353165373738343737386566386530343865343935646634396632
1006+ 363134663834613466316463222c22307830225d000000000000000000000000
1007+ "
1008+ )
1009+ . to_vec( ) ,
1010+ Some ( vec![
1011+ "\" mainnet\" " . to_string( ) ,
1012+ "\" eth_getBalance\" " . to_string( ) ,
1013+ "\" [\\ \" 0x551e7784778ef8e048e495df49f2614f84a4f1dc\\ \" ,\\ \" 0x0\\ \" ]\" "
1014+ . to_string( ) ,
1015+ ] ) ,
1016+ ) ,
7291017 ] ;
7301018
7311019 // [function_signature, expected]
7321020 let cheatcode_output_test_cases = vec ! [
7331021 // Should redact private key on output in all cases:
7341022 ( "createWallet(string)" , Some ( "<pk>" . to_string( ) ) ) ,
7351023 ( "deriveKey(string,uint32)" , Some ( "<pk>" . to_string( ) ) ) ,
1024+ // Should redact RPC URL if defined, except if referenced by an alias:
1025+ ( "rpcUrl(string)" , Some ( "<rpc url>" . to_string( ) ) ) ,
1026+ ( "rpcUrls()" , Some ( "<rpc url>" . to_string( ) ) ) ,
1027+ ( "rpcUrlStructs()" , Some ( "<rpc url>" . to_string( ) ) ) ,
7361028 ] ;
7371029
7381030 for ( function_signature, data, expected) in cheatcode_input_test_cases {
0 commit comments