@@ -12,14 +12,18 @@ library Safe {
1212
1313 /// forge-lint: disable-next-line(screaming-snake-case-const)
1414 Vm constant vm = Vm (address (bytes20 (uint160 (uint256 (keccak256 ("hevm cheat code " ))))));
15+ string constant SAFE_TRANSACTION_SERVICE_BASE_URL = "https://api.safe.global/tx-service " ;
16+ string constant PLUME_TRANSACTION_SERVICE_URL = "https://safe-transaction-plume.onchainden.com/api " ;
1517
1618 // https://github.com/safe-global/safe-smart-account/blob/release/v1.4.1/contracts/libraries/SafeStorage.sol
1719 bytes32 constant SAFE_THRESHOLD_STORAGE_SLOT = bytes32 (uint256 (4 ));
1820
19- // https://github.com/safe-global/safe-deployments/blob/v1.37.32/src/assets/v1.3.0/multi_send_call_only.json
20- address constant MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL = 0x40A2aCCbd92BCA938b02010E17A5b8929b49130D ;
21- address constant MULTI_SEND_CALL_ONLY_ADDRESS_EIP155 = 0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B ;
22- address constant MULTI_SEND_CALL_ONLY_ADDRESS_ZKSYNC = 0xf220D3b4DFb23C4ade8C88E526C1353AbAcbC38F ;
21+ // https://github.com/safe-global/safe-deployments/blob/c6a2025fca317b629d73d24b472c266418e2a4d6/src/assets/v1.3.0/multi_send_call_only.json
22+ address constant MULTI_SEND_CALL_ONLY_ADDRESS_V130_CANONICAL = 0x40A2aCCbd92BCA938b02010E17A5b8929b49130D ;
23+ address constant MULTI_SEND_CALL_ONLY_ADDRESS_V130_ZKSYNC = 0xf220D3b4DFb23C4ade8C88E526C1353AbAcbC38F ;
24+ // https://github.com/safe-global/safe-deployments/blob/c6a2025fca317b629d73d24b472c266418e2a4d6/src/assets/v1.4.1/multi_send_call_only.json
25+ address constant MULTI_SEND_CALL_ONLY_ADDRESS_V141_CANONICAL = 0x9641d764fc13c8B624c04430C7356C1C7C8102e2 ;
26+ address constant MULTI_SEND_CALL_ONLY_ADDRESS_V141_ZKSYNC = 0x0408EF011960d02349d50286D20531229BCef773 ;
2327
2428 error ApiKitUrlNotFound (uint256 chainId );
2529 error MultiSendCallOnlyNotFound (uint256 chainId );
@@ -29,8 +33,6 @@ library Safe {
2933 struct Instance {
3034 address safe;
3135 HTTP.Client http;
32- mapping (uint256 chainId = > string ) urls;
33- mapping (uint256 chainId = > MultiSendCallOnly) multiSendCallOnly;
3436 string requestBody;
3537 }
3638
@@ -58,54 +60,6 @@ library Safe {
5860 self.instances.push ();
5961 Instance storage i = self.instances[self.instances.length - 1 ];
6062 i.safe = safe;
61- // https://github.com/safe-global/safe-core-sdk/blob/4d89cb9b1559e4349c323a48a10caf685f7f8c88/packages/api-kit/src/utils/config.ts
62- i.urls[1 ] = "https://api.safe.global/tx-service/eth/api " ;
63- i.urls[10 ] = "https://api.safe.global/tx-service/oeth/api " ;
64- i.urls[56 ] = "https://api.safe.global/tx-service/bnb/api " ;
65- i.urls[100 ] = "https://api.safe.global/tx-service/gno/api " ;
66- i.urls[130 ] = "https://api.safe.global/tx-service/unichain/api " ;
67- i.urls[137 ] = "https://api.safe.global/tx-service/pol/api " ;
68- i.urls[196 ] = "https://api.safe.global/tx-service/okb/api " ;
69- i.urls[324 ] = "https://api.safe.global/tx-service/zksync/api " ;
70- i.urls[480 ] = "https://api.safe.global/tx-service/wc/api " ;
71- i.urls[999 ] = "https://api.safe.global/tx-service/hyper/api " ;
72- i.urls[1101 ] = "https://api.safe.global/tx-service/zkevm/api " ;
73- i.urls[5000 ] = "https://api.safe.global/tx-service/mantle/api " ;
74- i.urls[8453 ] = "https://api.safe.global/tx-service/base/api " ;
75- i.urls[42161 ] = "https://api.safe.global/tx-service/arb1/api " ;
76- i.urls[42220 ] = "https://api.safe.global/tx-service/celo/api " ;
77- i.urls[43114 ] = "https://api.safe.global/tx-service/avax/api " ;
78- i.urls[59144 ] = "https://api.safe.global/tx-service/linea/api " ;
79- i.urls[84532 ] = "https://api.safe.global/tx-service/basesep/api " ;
80- i.urls[98866 ] = "https://safe-transaction-plume.onchainden.com/api " ;
81- i.urls[534352 ] = "https://api.safe.global/tx-service/scr/api " ;
82- i.urls[11155111 ] = "https://api.safe.global/tx-service/sep/api " ;
83- i.urls[1313161554 ] = "https://api.safe.global/tx-service/aurora/api " ;
84-
85- // https://github.com/safe-global/safe-deployments/blob/v1.37.32/src/assets/v1.3.0/multi_send_call_only.json
86- i.multiSendCallOnly[1 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
87- i.multiSendCallOnly[10 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
88- i.multiSendCallOnly[56 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
89- i.multiSendCallOnly[100 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
90- i.multiSendCallOnly[130 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
91- i.multiSendCallOnly[137 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
92- i.multiSendCallOnly[196 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
93- i.multiSendCallOnly[324 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_ZKSYNC);
94- i.multiSendCallOnly[480 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
95- i.multiSendCallOnly[999 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
96- i.multiSendCallOnly[1101 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
97- i.multiSendCallOnly[5000 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
98- i.multiSendCallOnly[8453 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
99- i.multiSendCallOnly[42161 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
100- i.multiSendCallOnly[42220 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
101- i.multiSendCallOnly[43114 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
102- i.multiSendCallOnly[59144 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
103- i.multiSendCallOnly[84532 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
104- i.multiSendCallOnly[98866 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
105- i.multiSendCallOnly[534352 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
106- i.multiSendCallOnly[11155111 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
107- i.multiSendCallOnly[1313161554 ] = MultiSendCallOnly (MULTI_SEND_CALL_ONLY_ADDRESS_CANONICAL);
108-
10963 i.http.initialize ().withHeader ("Content-Type " , "application/json " ).withFollowRedirects (true );
11064 return self;
11165 }
@@ -114,20 +68,116 @@ library Safe {
11468 return self.instances[self.instances.length - 1 ];
11569 }
11670
117- function getApiKitUrl (Client storage self , uint256 chainId ) internal view returns (string memory ) {
118- string memory url = instance (self).urls[chainId];
119- if (bytes (url).length == 0 ) {
120- revert ApiKitUrlNotFound (chainId);
71+ function getApiKitUrl (Client storage , uint256 chainId ) internal pure returns (string memory ) {
72+ string memory thirdPartyApiKitUrl = getThirdPartyApiKitUrl (chainId);
73+ if (bytes (thirdPartyApiKitUrl).length > 0 ) {
74+ return thirdPartyApiKitUrl;
75+ }
76+
77+ return getTransactionServiceUrl (chainId);
78+ }
79+
80+ // Mirrors safe-global/safe-core-sdk/packages/api-kit/src/utils/config.ts on main.
81+ function getNetworkShortName (uint256 chainId ) internal pure returns (string memory ) {
82+ if (chainId == 1 ) return "eth " ;
83+ if (chainId == 10 ) return "oeth " ;
84+ if (chainId == 50 ) return "xdc " ;
85+ if (chainId == 56 ) return "bnb " ;
86+ if (chainId == 100 ) return "gno " ;
87+ if (chainId == 130 ) return "unichain " ;
88+ if (chainId == 137 ) return "pol " ;
89+ if (chainId == 143 ) return "monad " ;
90+ if (chainId == 146 ) return "sonic " ;
91+ if (chainId == 196 ) return "okb " ;
92+ if (chainId == 204 ) return "opbnb " ;
93+ if (chainId == 232 ) return "lens " ;
94+ if (chainId == 324 ) return "zksync " ;
95+ if (chainId == 480 ) return "wc " ;
96+ if (chainId == 988 ) return "stable " ;
97+ if (chainId == 999 ) return "hyper " ;
98+ if (chainId == 1101 ) return "zkevm " ;
99+ if (chainId == 3338 ) return "peaq " ;
100+ if (chainId == 3637 ) return "btc " ;
101+ if (chainId == 5000 ) return "mantle " ;
102+ if (chainId == 8453 ) return "base " ;
103+ if (chainId == 9745 ) return "plasma " ;
104+ if (chainId == 10143 ) return "monad-testnet " ;
105+ if (chainId == 10200 ) return "chi " ;
106+ if (chainId == 16661 ) return "0g " ;
107+ if (chainId == 42161 ) return "arb1 " ;
108+ if (chainId == 42220 ) return "celo " ;
109+ if (chainId == 43111 ) return "hemi " ;
110+ if (chainId == 43114 ) return "avax " ;
111+ if (chainId == 57073 ) return "ink " ;
112+ if (chainId == 59144 ) return "linea " ;
113+ if (chainId == 80069 ) return "bep " ;
114+ if (chainId == 80094 ) return "berachain " ;
115+ if (chainId == 81224 ) return "codex " ;
116+ if (chainId == 84532 ) return "basesep " ;
117+ if (chainId == 534352 ) return "scr " ;
118+ if (chainId == 747474 ) return "katana " ;
119+ if (chainId == 11155111 ) return "sep " ;
120+ if (chainId == 1313161554 ) return "aurora " ;
121+ revert ApiKitUrlNotFound (chainId);
122+ }
123+
124+ function getTransactionServiceUrl (uint256 chainId ) internal pure returns (string memory ) {
125+ return string .concat (SAFE_TRANSACTION_SERVICE_BASE_URL, "/ " , getNetworkShortName (chainId), "/api " );
126+ }
127+
128+ function getThirdPartyApiKitUrl (uint256 chainId ) internal pure returns (string memory ) {
129+ if (chainId == 98866 ) {
130+ return PLUME_TRANSACTION_SERVICE_URL;
121131 }
122- return url ;
132+ return "" ;
123133 }
124134
125- function getMultiSendCallOnly (Client storage self , uint256 chainId ) internal view returns (MultiSendCallOnly) {
126- MultiSendCallOnly multiSendCallOnly = instance (self).multiSendCallOnly[chainId];
127- if (address (multiSendCallOnly) == address (0 )) {
135+ function getMultiSendCallOnly (Client storage , uint256 chainId ) internal pure returns (MultiSendCallOnly) {
136+ address multiSendCallOnly = getThirdPartyMultiSendCallOnlyAddress (chainId);
137+ if (multiSendCallOnly == address (0 )) {
138+ multiSendCallOnly = getOfficialMultiSendCallOnlyAddress (chainId);
139+ }
140+ if (multiSendCallOnly == address (0 )) {
128141 revert MultiSendCallOnlyNotFound (chainId);
129142 }
130- return multiSendCallOnly;
143+ return MultiSendCallOnly (multiSendCallOnly);
144+ }
145+
146+ function getOfficialMultiSendCallOnlyAddress (uint256 chainId ) internal pure returns (address ) {
147+ if (
148+ chainId == 1 || chainId == 10 || chainId == 56 || chainId == 100 || chainId == 130 || chainId == 137
149+ || chainId == 196 || chainId == 480 || chainId == 999 || chainId == 1101 || chainId == 5000
150+ || chainId == 8453 || chainId == 42161 || chainId == 42220 || chainId == 43114 || chainId == 59144
151+ || chainId == 84532 || chainId == 534352 || chainId == 11155111 || chainId == 1313161554
152+ ) {
153+ return MULTI_SEND_CALL_ONLY_ADDRESS_V130_CANONICAL;
154+ }
155+
156+ if (chainId == 324 ) {
157+ return MULTI_SEND_CALL_ONLY_ADDRESS_V130_ZKSYNC;
158+ }
159+
160+ if (
161+ chainId == 50 || chainId == 143 || chainId == 146 || chainId == 204 || chainId == 988 || chainId == 3338
162+ || chainId == 3637 || chainId == 9745 || chainId == 10143 || chainId == 10200 || chainId == 16661
163+ || chainId == 43111 || chainId == 57073 || chainId == 80069 || chainId == 80094 || chainId == 81224
164+ || chainId == 747474
165+ ) {
166+ return MULTI_SEND_CALL_ONLY_ADDRESS_V141_CANONICAL;
167+ }
168+
169+ if (chainId == 232 ) {
170+ return MULTI_SEND_CALL_ONLY_ADDRESS_V141_ZKSYNC;
171+ }
172+
173+ return address (0 );
174+ }
175+
176+ function getThirdPartyMultiSendCallOnlyAddress (uint256 chainId ) internal pure returns (address ) {
177+ if (chainId == 98866 ) {
178+ return MULTI_SEND_CALL_ONLY_ADDRESS_V130_CANONICAL;
179+ }
180+ return address (0 );
131181 }
132182
133183 function getNonce (Client storage self ) internal view returns (uint256 ) {
0 commit comments