1
+ import { isAddress } from "viem" ;
1
2
import { providers , utils } from "ethers" ;
2
3
import bs58 from "bs58" ;
3
4
import { BigNumber , chainIsEvm , chainIsSvm } from "./" ;
4
5
6
+ /**
7
+ * Verify whether an address' bytecode resembles an EIP-7702 delegation.
8
+ * @param code Bytecode for a given address.
9
+ * @returns True if the bytecode resembles an EIP-7702 delegation, otherwise false.
10
+ */
11
+ export function is7702Delegate ( code : string ) : boolean {
12
+ // Sample 7702 delegation bytecode: 0xef010063c0c19a282a1b52b07dd5a65b58948a07dae32b
13
+ return code . length === 48 && code . startsWith ( "0xef0100" ) && isAddress ( `0x${ code . slice ( 8 ) } ` ) ;
14
+ }
15
+
5
16
/**
6
17
* Checks if a contract is deployed at the given address
7
18
* @param address The ETH address to check
8
19
* @param provider A valid Ethers.js provider
20
+ * @param ignore7702 A boolean to indicate whether EIP-7702 delegations should be considered as contract code.
9
21
* @returns A boolean indicating if a contract is deployed at the given address or not (true = contract, false = no contract)
10
22
*/
11
- export async function isContractDeployedToAddress ( address : string , provider : providers . Provider ) : Promise < boolean > {
23
+ export async function isContractDeployedToAddress (
24
+ address : string ,
25
+ provider : providers . Provider ,
26
+ ignore7702 = false
27
+ ) : Promise < boolean > {
12
28
// A base case for if the address is null or malformed
13
- if ( ! address || ! utils . isAddress ( address ) ) {
29
+ if ( ! address || ! isAddress ( address ) ) {
14
30
return false ;
15
31
}
16
- // Retrieve the code at the address
32
+
17
33
const code = await provider . getCode ( address ) ;
18
- // If the code is not empty, then there is a contract at this address
19
- return code !== "0x" ;
34
+ if ( code === "0x" ) {
35
+ return false ;
36
+ }
37
+
38
+ // Ignore EIP-7702 delegations if ignore7702 was set.
39
+ if ( ignore7702 ) {
40
+ return ! is7702Delegate ( code ) ;
41
+ }
42
+
43
+ return true ;
20
44
}
21
45
22
46
export function compareAddresses ( addressA : string , addressB : string ) : 1 | - 1 | 0 {
@@ -56,7 +80,7 @@ export function toEvmAddress(hexString: string): string {
56
80
}
57
81
58
82
export function isValidEvmAddress ( address : string ) : boolean {
59
- if ( utils . isAddress ( address ) ) {
83
+ if ( isAddress ( address ) ) {
60
84
return true ;
61
85
}
62
86
// We may throw an error here if hexZeroPadFails. This will happen if the address to pad is greater than 20 bytes long, indicating
@@ -65,7 +89,7 @@ export function isValidEvmAddress(address: string): boolean {
65
89
// For both cases, this indicates that the address cannot be casted as a bytes20 EVM address, so we should return false.
66
90
try {
67
91
const evmAddress = utils . hexZeroPad ( utils . hexStripZeros ( address ) , 20 ) ;
68
- return utils . isAddress ( utils . getAddress ( evmAddress ) ) ;
92
+ return isAddress ( utils . getAddress ( evmAddress ) ) ;
69
93
} catch ( _e ) {
70
94
return false ;
71
95
}
0 commit comments