合约地址是智能合约在区块链上的地址。它在合约部署时产生,没有私钥,也是人们在代币旁边写「CA」时所指的那串字符。
在以太坊和所有 EVM 链上,它看起来和钱包地址一模一样:0x 后接 40 个十六进制字符。USDT、USDC 这样的代币本身就是合约,所以代币的地址就是合约地址。它和钱包地址的区别在于背后是什么:是代码和存储,而不是一个持有私钥的人。
这个词会在三个地方出现:往钱包里添加自定义代币时、区块浏览器把一个地址标注为合约时,以及有人发布一个新币的 CA 时。本指南解释这个地址标识的是什么、它是如何生成的、如何把它和钱包地址区分开、在哪里找到代币的真实地址,以及把资金转到合约地址会发生什么。
简要版
- 合约地址指向代码,钱包地址指向持有密钥的人。在 EVM 链上两者格式相同,所以光看格式分不出谁是谁。区块浏览器或一次 eth_getCode 调用可以。
- 在 EVM 链上,地址是 0x + 40 个十六进制字符,由部署者的地址和 nonce 推导而来,或者在 CREATE2 下由一个 salt 推导而来。Tron 使用以 T 开头的 34 个字符,Solana 使用 base58 格式的 mint 地址。
- 从发行方的网站或文档复制代币地址,然后检查区块浏览器是否显示已验证的源码、大量持有者和较长的历史。骗子代币会沿用真币的名称和代码。
- 大多数代币合约无法退回转到它自己地址上的代币。充值要转到钱包地址;与合约交互要通过 dApp 或一个知道其函数的钱包。
1. 什么是合约地址?
在以太坊以及按它的模式构建的链上,每个账户都有一个地址。账户分两种。外部账户(externally owned account)属于持有其私钥的人。合约账户存放一个程序以及该程序维护的数据,它的地址就是合约地址。ethereum.org 的文档说得很直接:合约账户没有私钥,它们由智能合约代码的逻辑控制。
合约由一笔交易一次性部署,在那一刻获得地址,并在链存在期间一直保留它。任何人都可以向这个地址发送交易来调用合约的某个函数。一次代币转账或在去中心化交易所上的一次兑换,就是一笔发给合约的交易。
代币是最常见的情况。USDT、USDC、WETH 以及其他所有 ERC-20 代币都是维护一张余额表的合约。因此代币的地址就是合约地址,也是钱包显示一个它还不认识的代币所需要的唯一信息。
2. 加密货币里的「CA」是什么意思?
CA 是 contract address(合约地址)的缩写。在 X、Telegram 和 Discord 上,关于新代币的帖子通常以 CA 加地址结尾,因为代币的名称和代码不是唯一的,而地址是唯一的。交易网站和钱包也用同样的缩写。
在 Solana 上,CA 是代币的 mint 地址,也就是定义代币供应量和小数位数的那个账户。在以太坊、BNB Chain、Base 和其他 EVM 网络上,它是 ERC-20 或 BEP-20 合约的地址。两种情况下,把这个地址粘贴到钱包或浏览器里,就能找到别人所说的那个代币。这也是假 CA 成为常见骗局的原因:一个同名的仿冒代币会有一个不同的地址。
3. 合约地址长什么样?
格式取决于链,而且和这条链用于钱包地址的格式相同。下面是两种广泛使用的稳定币的官方地址,取自发行方的页面:
| 网络 | 代币 | 合约地址 | 格式 |
|---|---|---|---|
| Ethereum | USDT(ERC-20) | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | 0x + 40 个十六进制字符 |
| Ethereum | USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | 0x + 40 个十六进制字符 |
| Base | USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | 0x + 40 个十六进制字符 |
| Arbitrum One | USDC | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 | 0x + 40 个十六进制字符 |
| Polygon PoS | USDC | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 | 0x + 40 个十六进制字符 |
| Tron | USDT(TRC-20) | TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t | 以 T 开头的 34 个 base58check 字符 |
| Solana | USDC(mint 地址) | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v | 32 到 44 个 base58 字符 |
以太坊、Base、Arbitrum 和 Polygon 的条目来自 Circle 的 USDC 合约地址列表,USDT 的条目来自 Tether 的支持协议页面。USDC 在每条链上的地址都不同:名称相同并不代表是同一个合约。EVM 地址中的大小写字母构成一个校验和,由 EIP-55 定义;全小写的写法是同一个地址,浏览器和钱包两种都接受。
比特币没有合约地址。以 3 或 bc1 开头的比特币地址可以编码一个脚本,但地址上并没有一个可供调用的程序。这个概念属于以太坊、Tron 和 Solana 这类基于账户的链。
4. 合约地址与钱包地址:有什么区别?
在 EVM 链上两者看起来完全一样,所以区别在于是什么在控制这个地址。
| 钱包地址(外部账户) | 合约地址 | |
|---|---|---|
| 由什么控制 | 一个私钥,通常由助记词派生 | 合约的代码;没有私钥 |
| 能否发起交易 | 能 | 不能。只有在交易或另一个合约调用它时才会运行 |
| 是否包含代码 | 不包含,除非按 EIP-7702 委托给代码 | 包含,还有自己的存储 |
| 如何创建 | 免费:由公钥派生,不需要交易 | 通过一笔支付 gas 的部署交易 |
| 典型用途 | 收款、签署交易 | 代币、交易所、借贷池、NFT 系列、跨链桥 |
| 在区块浏览器上 | 显示为普通地址 | 标注为合约,并有一个 Contract 标签 |
唯一的灰色地带是 EIP-7702,它自 2025 年 5 月的 Pectra 升级起在以太坊上生效。它允许钱包地址给自己挂上委托代码,从而批量执行调用或让别人代付手续费。密钥仍然控制着账户,账户仍然可以发送交易,所以它仍是一个附带代码的钱包地址。
要区分两者,在区块浏览器上打开这个地址:合约会有一个 Contract 标签、一个创建者地址,以及(如果源码已发布)已验证的代码。在代码里,JSON-RPC 方法 eth_getCode 会返回存储在该地址上的字节码,钱包地址则只返回 0x。Etherscan 指南展示了这些标签各在哪里。
5. 合约地址是如何生成的?
地址是算出来的,不是选出来的,每条链有自己的规则:
- 以太坊和 EVM 链(CREATE)
- 地址是对部署者地址及其 nonce(该地址已发送的交易数)做 Keccak-256 哈希后的最后 20 个字节。从同一个账户部署两次会得到两个不同的地址,因为 nonce 已经往前走了。
- 以太坊和 EVM 链(CREATE2)
- 一个合约可以在一个由它自己的地址、它选定的 salt 和创建代码的哈希算出的地址上部署另一个合约:keccak256(0xff ++ address ++ salt ++ keccak256(init_code))[12:]。地址在任何东西部署之前就已经确定,这就是一个合约能在许多条链上出现在同一个地址的原因。
- Tron
- Tron 地址是以 0x41 开头的 21 个字节,显示为以 T 开头的 34 个 base58check 字符。合约地址与钱包地址格式相同,由部署交易的 ID 和部署者的地址推导而来。
- Solana
- 程序的地址是存放其可执行代码的账户的公钥。代币由其 mint 账户的地址标识,该账户归 Token Program 所有。持有该代币的钱包会为每个 mint 得到一个单独的代币账户。
这些规则见 ethereum.org 的账户文档、EIP-1014(针对 CREATE2)、Tron 账户参考和 Solana 代币文档。
6. 代币地址和合约地址是一回事吗?
在 EVM 链上,是的。代币地址就是该代币合约的合约地址,钱包、浏览器和交易所用这两个名字指同一串字符。往钱包里添加自定义代币就是粘贴这个地址;然后钱包会从合约本身读取代币符号和小数位数,所以地址错了显示的是一个错误的代币,而不是报错。
有两种情况需要额外的标识符。NFT 由系列的合约地址加上一个 token ID 来标识,因为整个系列都在一个合约里。在 Solana 上,代币地址是 mint 地址,而你持有的余额存放在一个与你的钱包关联的代币账户里,而不是在 mint 上。
7. 如何找到代币的合约地址?
从发行方控制的来源获取,然后在浏览器上确认。
- 发行方的网站或文档
- 稳定币发行方、协议和大多数项目都会按链公布自己的地址。Circle 和 Tether 分别为 USDC 和 USDT 维护着一个页面,上表中的条目就来自那里。
- CoinMarketCap 和 CoinGecko
- 代币页面在 Contracts 一栏列出每条链上的合约地址,带有复制按钮和指向浏览器的链接。
- 区块浏览器
- 在 Etherscan、BscScan、Polygonscan、Tronscan 或 Solscan 上搜索代币名称。浏览器会标记出公认的那个代币并显示持有者数量;一个同名但只有十个持有者的副本是另一个代币。
- 你的钱包或交易所
- 钱包在代币详情页显示地址。交易所在充值和提币页面显示它,同时注明地址所属的网络。
复制整串字符,并把网络一起记下来。Base 上的 USDC 地址在 Arbitrum 上毫无意义,在错误的链上查询时浏览器会显示一个空地址。
8. 如何验证一个合约地址是真的?
代币的名称和符号在合约里只是自由文本,所以任何人都能部署第二个 USDC。以下检查能把真合约和仿冒品区分开:
- 与发行方比对
- 地址必须与发行方网站或文档上的那个逐字符完全一致。不要只比对开头和结尾的几个字符;仿冒地址就是专门生成来让这几位相同的。
- 查看源码是否已验证
- 在 Etherscan 及类似浏览器上,Contract 标签会显示部署者是否发布了源码,以及浏览器是否重新编译并与字节码匹配。对任何广泛使用的代币来说,未验证的字节码都是一个警示信号。
- 检查持有者、存在时间和活跃度
- 真正的稳定币合约有数百万笔转账和多年的历史。上周才部署、只有寥寥几个持有者且没有已验证源码的合约是另一个代币,不管它叫什么名字。
- 读一读代币的规则
- 浏览器和代币扫描工具会标记那些所有者可以随意增发、暂停转账、修改费用或阻止卖出的合约。代理合约地址不变却可以更换实现,所以要查清是谁控制升级。
- 核对链
- 同一个项目在不同链上有不同的地址,所以要确保浏览器、钱包和来源指的都是同一条网络。
这篇 Etherscan 指南逐一介绍了这些检查用到的 Contract 标签以及 Read Contract 和 Write Contract 视图。
9. 可以把加密货币转到合约地址吗?
可以,结果取决于合约。往借贷池存款、在去中心化交易所买币或铸造 NFT,都是通过向合约发送一笔交易来完成的,通常附带一个函数调用,并通过一个知道合约接口的钱包或 dApp 来进行。
要避免的错误是把代币转到该代币自己的合约地址。ERC-20 标准定义了转账、授权和余额函数,却没有任何能让合约把代币退回的函数,所以误转到代币合约的币通常就没了,除非发行方内置了恢复函数并同意使用它。大多数从未设计为接收普通转账的合约也是如此:有的会拒绝,有的会默默接受。
交易所或个人向你要充值时,给你的是一个钱包地址。协议希望你交互时,dApp 会替你构建交易。如果你发现自己正在把代币的合约地址粘贴到转账的收款人栏里,停下来检查一下自己在做什么。
10. 合约地址在每条区块链上都一样吗?
不一样,除非部署者刻意这么做。上面的 USDC 表格显示同一资产在四条 EVM 链上有四个不同的地址,因为每次部署都是来自一个 nonce 不同的账户的一笔单独交易。跨链桥接版本的代币(常带有 .e 之类的后缀)有自己的地址,所以浏览器在一条网络上可能显示不止一个叫 USDC 的代币。
跨链相同的地址可以通过 CREATE2 实现,或者用一个全新账户在每条链上重放同一笔已签名的部署交易。Multicall3 是钱包和库常用的辅助合约,正因如此它在一百多条链上都位于 0xcA11bde05977b3631167028862bE2a173976CA11,它的部署列表就显示了这一点。大多数代币不是这样部署的,所以要在你正在使用的那条链上查地址。
如果你不确定钱包连接的是哪条网络,链 ID 列表把每个链 ID 对应到它所属的网络和浏览器。
11. 在代码中检查地址
允许用户粘贴代币地址或收款地址的应用,应该在构建交易之前先校验格式。ChainGate 的 SDK 可以校验比特币、以太坊、Litecoin、Dogecoin、Bitcoin Cash 以及你注册的任何 EVM 网络的地址,并会拒绝大小写混合校验和不匹配的 EVM 地址:
import { ChainGate, isValidEvmAddress } from 'chaingate';
const cg = new ChainGate({ apiKey: process.env.CHAINGATE_API_KEY });
// Format checks: true for a well-formed address, false otherwise
cg.networks.ethereum.isValidAddress('0xdAC17F958D2ee523a2206206994597C13D831ec7'); // true (USDT contract)
cg.networks.ethereum.isValidAddress('0xD8DA6bf26964af9d7eed9e03e53415d37aa96045'); // false (EIP-55 checksum does not match)
isValidEvmAddress('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'); // true (USDC contract)
// Bitcoin: validate and classify the address type
cg.networks.bitcoin.isValidAddress('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'); // true
cg.networks.bitcoin.identifyAddressType('bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'); // 'segwit-p2wpkh'格式校验只能说明这串字符是一个格式正确的地址,不能说明那里是否有代码。要知道这一点,请在 RPC 端点上调用 eth_getCode:合约会返回它的字节码,钱包地址则返回 0x。地址校验文档列出了所有支持的网络以及 SDK 能识别的比特币地址类型。
12. 接下来看什么
合约地址告诉你在和哪个程序打交道,交易哈希告诉你发起了哪次调用,而 Etherscan 指南展示了如何在浏览器上读懂这两者。每次调用合约都要花 gas,Gas 追踪器显示现在在各网络上这要花多少。如果你希望用一个 SDK 就把比特币、以太坊和其他网络上的地址校验、余额和转账都处理好,ChainGate 就能做到。
常见问题
加密货币里的合约地址是什么?
智能合约在区块链上的地址:这是一个由交易部署的程序,有自己的存储,没有私钥。代币、去中心化交易所、借贷池和 NFT 系列都是合约,所以各自都有一个合约地址。在以太坊和其他 EVM 链上,它是 0x 后接 40 个十六进制字符,与钱包地址格式相同。
加密货币里的 CA 是什么意思?
CA 是 contract address(合约地址)的缩写。人们把它贴在代币名称旁边,因为名称和代码不是唯一的,而地址是唯一的。在 Solana 上,CA 是代币的 mint 地址;在以太坊、BNB Chain 或 Base 上,它是代币合约的地址。
合约地址和钱包地址是一回事吗?
不是。钱包地址由私钥控制,可以发起交易。合约地址由部署在它上面的代码控制,没有私钥,只有在交易调用它时才会动作。在 EVM 链上两者都是同样的 0x 格式,所以要在区块浏览器上区分它们(合约会有一个 Contract 标签),或者用 eth_getCode RPC 调用,它对钱包地址返回 0x。
合约地址长什么样?
以太坊、BNB Chain、Polygon、Arbitrum、Base 和其他 EVM 链:0x 加 40 个十六进制字符,例如 USDT 的地址 0xdAC17F958D2ee523a2206206994597C13D831ec7。Tron:以 T 开头的 34 个 base58check 字符,例如 USDT 的地址 TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t。Solana:32 到 44 个字符的 base58 mint 地址,例如 USDC 的地址 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v。
如何找到代币的合约地址?
从发行方的网站或文档获取,或者从 CoinMarketCap 或 CoinGecko 上代币页面的 Contracts 一栏获取,然后在同一条链的区块浏览器上确认:已验证的源码、大量持有者和长期的转账历史标志着真正的合约。钱包在代币详情页显示地址,交易所在充值页面显示。
如何知道一个地址是不是合约?
在区块浏览器上打开它。合约页面会显示一个 Contract 标签、创建者地址,以及(如果已发布)已验证的源码。在代码里,eth_getCode RPC 方法对合约返回字节码,对钱包地址返回 0x。
可以把代币转到合约地址吗?
只有当合约被设计为接收它们时才可以,比如借贷池或交易所,而且通常要通过一个会附上正确函数调用的 dApp。把代币转到该代币自己的合约地址通常会丢失,因为 ERC-20 标准没有把它们退回的函数。给交易所充值和给个人付款,永远都是转到钱包地址。
什么是代币地址?
代币的智能合约的合约地址。钱包、浏览器和交易所用代币地址和合约地址指同一串字符。在 Solana 上,代币地址是 mint 地址;NFT 由其系列的合约地址加上一个 token ID 来标识。
合约地址在所有链上都一样吗?
默认不一样。USDC 在以太坊、Base、Arbitrum 和 Polygon 上的地址各不相同,因为每次部署都是一笔单独的交易。项目可以通过 CREATE2 或重放同一笔已签名的部署交易在许多链上获得相同的地址,Multicall3 就是这么做的,但你始终应该在自己使用的那条链上查地址。
智能合约有私钥吗?
没有。合约账户由它的代码控制。如果代码包含所有者函数,所有者是一个单独的地址,通常是一个钱包或多签,它持有自己的密钥。已放弃所有权的合约没有任何人能再改动它。
使用 ChainGate 构建
把这些想法落地 —— ChainGate 提供钱包、交易与托管 RPC,一次安装即可覆盖以太坊以及 20 多条其他区块链。