想象你准备开一家“无人自动咖啡店”:顾客扫码付款,机器自动磨豆、萃取、出杯,全程无需店员。支撑这台机器稳定运转的核心,是一份写在“链上”的流程手册——每一条规则(收款多少、何时出杯、找零多少)都公开透明、无法事后篡改。这份手册就是智能合约。问题来了:你绝不会把一套没试过的流程直接砸进重金租来的店面里。你会先在自家厨房照着手册试做、尝味道;再请朋友来家里试饮、提意见;最后才正式挂招牌营业。智能合约的测试与部署,正是这样一条从“自家厨房”走向“正式开业”的路:单元测试、集成测试、测试网演练,再到主网部署与上线后的运营监控。本文就沿着这条开店之路,带你完整走一遍合约测试与部署的每一个关键环节。

岗位关联

掌握测试与部署全流程,是智能合约从“能跑”走向“敢上线”的分水岭;对 AI 从业者来说,这也是参与 DeFi、链上 AI 等产品交付时最核心的工程能力。

目录
  1. 可视化演示
  2. 测试基础概念
  3. 测试框架工具
  4. 单元测试编写
  5. 集成测试实战
  6. 部署前检查
  7. 合约部署流程
  8. 部署后运营
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

演示Hardhat/Foundry单元模糊不变性测试执行、代理合约部署升级模式、CI/CD多签流水线Gas快照三大模式交互动画。

本节配有交互动效(进入视口后自动加载,约 3KB)。

合约测试框架执行 Hardhat/Foundry执行单元集成测试用例 模糊测试注入随机输入发现边界缺陷 coverage = lines_tested / lines_total 单元+集成+模糊测试保障合约逻辑安全

测试基础概念

开店第一步不是选址,而是“试做配方”。咖啡店的配方写着“先磨豆 20 克,再加热水到 92 度,萃取 30 秒”,每一条都是给机器的指令;智能合约则把“收钱、记录、转账”写成代码,部署上链后谁都无法偷改。正因如此,做错一个小步骤的代价远超普通软件——代码一旦上链就成了“法律”,所以在开业前,我们要用最低的成本把所有错误找出来,这就是测试存在的意义。

测试界有一个经典的“测试金字塔”:底座是最多、最便宜、最快的单元测试,逐个验证合约里每个函数;中间是集成测试,检查多个合约如何配合;塔尖是少量端到端系统测试,模拟真实用户完整走一遍流程。越靠近塔底,发现问题越早、修复成本越低。对一份合约来说,最直观的质量指标是测试通过率——跑完所有用例后,有多少比例通过了检查。

除了通过率,工程上还关心测试环境。本地可以起一个模拟区块链(Hardhat Network / Anvil),速度快、零成本;再把同样的用例跑在测试网上(如 Sepolia),因为测试网与主网规则几乎一致,只是代币没有真实价值。多一层环境,就多一分确定性。通过率不是“目标”而是“底线”,它要和覆盖率等指标一起,构成“敢不敢开业”的判断依据。回到咖啡店:通过率 100% 意味着你试做了 100 道工序、道道符合预期。但这只是“试做”环节的结束,后面还有宴席排练和试营业等着你——这正是接下来要讲的内容。

Rpass=NpassNtotal×100%\displaystyle R_{pass} = \frac{N_{pass}}{N_{total}} \times 100\%
通过率 = 通过的用例数 ÷ 总用例数 × 100%。它回答“测过的场景里有多少是符合预期的”。
  1. 统计通过用例数把测试结果中行为符合预期的用例数记为 N_pass,它代表“配方步骤做对了”的条数。
    NpassN_{pass}
  2. 统计总用例数所有被测场景的总数记为 N_total,无论通过还是失败都算在内。
    NtotalN_{total}
  3. 计算比值两者相除再乘以 100%,得到通过率 R_pass;它越高,说明开业前发现的问题越少。
    NpassNtotal×100%\frac{N_{pass}}{N_{total}} \times 100\%

测试框架工具

厨房里不能只有一口锅。有人喜欢即开即用的小焖锅,有人喜欢现代化整体橱柜,还有人追求专业私厨的效率。对应到合约开发:Remix 是浏览器里即开即用的 IDE,把代码拖进来就能写、能跑测试,适合快速验证小合约;Hardhat 是目前最主流的框架,用 JavaScript/TypeScript 编写测试,插件生态丰富;Foundry 则用 Solidity 原生编写测试,执行速度极快,内置模糊测试和主网分叉能力,近年非常流行。

选框架本质是选“厨房风格”:团队熟悉 JS,选 Hardhat 上手最顺;追求极致速度和链上实测,Foundry 更香;只是快速验证想法,Remix 足够。不同的工具决定了单条用例的执行耗时 t,而总测试时间由用例规模决定。

试想一下:同一套 2000 条用例,Hardhat 可能跑 3 分钟,Foundry 可能只要 30 秒。开业筹备期,时间就是金钱——选择合适“厨具”,能让整个试做流程快一个数量级,这也是大项目选型时最现实的考量。

Ttotal=n×tcase\displaystyle T_{total} = n \times t_{case}
总测试时间 = 用例总数 × 单条用例耗时。几千条用例跑下去,这个乘积直接决定 CI 里能不能按时跑完。
  1. 用例总数 n测试套件里所有用例的数量,越多覆盖越全,但也越耗时。
    nn
  2. 单条用例耗时 t每条用例从部署环境到执行断言的平均时间,由框架和硬件决定。
    tcaset_{case}
  3. 相乘得总时长两者相乘得到总测试时间 T_total,它是衡量框架效率的核心指标。
    n×tcasen \times t_{case}

单元测试编写

试做配方时,你不会一大锅煮完再尝,而是把“磨豆、加热、萃取、打奶泡”拆成一个个小步骤,每步单独品尝。单元测试就是给合约的“每个函数”单独建一个小考场:在 Hardhat 里用 describe/it 组织用例,用断言(assert / expect)检查函数返回值、状态变量变化、事件是否如期发出。比如测试 buyCoffee 函数,就要断言转账后余额增加了、返回的找零正确了、售出杯数加一了。

好的单元测试会同时覆盖“正常路径”和“异常路径”:require 条件不满足时必须 revert 回滚;权限不足时,只有 owner 能通过、其他人一律被拒绝。这里有一个关键指标——分支覆盖率,它衡量所有 if/require 分支中有多少被执行过。

比如“磨豆”分支里有“豆子充足”和“豆子耗尽”两条路,两条都测得才算覆盖了这步工序。把每个函数当成一道工序来验收,验证完正常流程还要故意“捣乱”验证异常流程,这样端出来的每一杯咖啡——也就是上链后的每一次调用——才让人放心。

Cbranch=BcoveredBtotal×100%\displaystyle C_{branch} = \frac{B_{covered}}{B_{total}} \times 100\%
分支覆盖率 = 被执行到的分支数 ÷ 总分支数 × 100%。覆盖率越高,藏在角落里的逻辑 bug 越难遁形。
  1. 统计已覆盖分支 B_covered测试执行过程中真实进入过的 if/require 分支数量。
    BcoveredB_{covered}
  2. 统计总分支 B_total合约代码中所有可能的分支路径总数。
    BtotalB_{total}
  3. 计算覆盖率两者相除再乘 100%,得到分支覆盖率 C_branch,是衡量测试充分度的重要参考。
    BcoveredBtotal×100%\frac{B_{covered}}{B_{total}} \times 100\%

集成测试实战

真正开店时,煮咖啡只是其中一环——前面有收银,后面有库存。合约世界也是如此:一次业务往往要多个合约接力完成。用户先授权代币给借贷池合约,借贷池再去问价格预言机,最后才完成借贷。集成测试就是检查“宴席上每道菜如何配合”。

集成测试的常用手段是“主网分叉”:在本地把主网某个区块的状态完整克隆一份,然后让你的合约跟真实的代币、真实的借贷池去交互。这相当于排练时把真朋友请来当食客,场景绝对真实,风险却为零。再往上是端到端测试和测试网演练:像顾客一样扫码、付款、拿咖啡,走完整条业务链路,测试网用假币模拟真钱流动。需要警惕的是,合约之间的交互面会随数量爆炸式增长。

宴席上有一道菜出了问题,整桌客人都可能不满意。集成测试的价值,就是在“试营业”之前,先把代币合约、借贷池、预言机这条完整链条反复演练几十遍,确保正式开业时每一环都咬合紧密。

Kpairs=n×(n−1)2\displaystyle K_{pairs} = \frac{n \times (n - 1)}{2}
两两组合数 = n × (n-1) ÷ 2。3 个合约有 3 种组合,10 个合约就有 45 种组合,必须系统化测试而非碰运气。
  1. 合约数量 n参与同一业务流程的合约总数,它是组合爆炸的基数。
    nn
  2. 计算两两组合数n 个合约中任取两个交互的组合数为 n(n-1)/2,由此得到 K_pairs。
    n×(n−1)2\frac{n \times (n - 1)}{2}
  3. 理解含义组合数随 n 平方级增长,这正是集成测试必须自动化、按优先级覆盖交互路径的原因。
    KpairsK_{pairs}

部署前检查

开业前夜,你会做三件事:复核配方(代码审计)、确认钥匙在谁手里(权限核查)、盘算装修预算(成本估算)。智能合约上线前同样有一份“开业检查清单”。

代码审计分人工与工具两条腿:安全公司逐行读代码找漏洞,自动化工具如 Slither 能扫出重入、整数溢出等常见病。权限核查要确认 owner 是谁、哪些函数只有管理员能调用,最好把 owner 换成多签钱包,避免一把钥匙丢了的单点风险。而成本估算决定你“开不开得起这家店”:部署一笔交易要付的 Gas 费,由消耗的 Gas 数量和当前 Gas 单价共同决定,主网高峰期单价可能翻好几倍。

把所有检查项固定成一份部署清单(Deployment Checklist),逐项打勾:审计通过、权限收敛、预算充足、依赖地址正确。就像开业前把消防检查、卫生许可、门锁测试全部过一遍,这份清单能帮你挡掉绝大多数“开业当天才发现”的尴尬。

Cost=Gused×Pgas\displaystyle Cost = G_{used} \times P_{gas}
部署成本 = 消耗的 Gas 数量 × Gas 单价。提前估算部署与用户调用成本,才能定好“菜单价格”。
  1. 消耗的 Gas 数量 G执行部署或调用交易时,EVM 按操作复杂度计量的燃料消耗量。
    GusedG_{used}
  2. Gas 单价 P当前网络每个 Gas 单位的价格,随网络拥堵程度动态波动。
    PgasP_{gas}
  3. 相乘得到总成本两者相乘得到该笔交易的预估成本 Cost,是部署预算和定价策略的核心依据。
    Gused×PgasG_{used} \times P_{gas}

合约部署流程

正式开业那天,仪式有三步:剪彩(用部署账号签下交易)、挂招牌(把源码公开验证)、等第一批顾客确认(新区块确认)。工程上,部署不会靠手工点按钮,而是交给部署脚本。一条 hardhat run scripts/deploy.js --network sepolia 命令,脚本负责构造参数、预估 Gas、签名并广播交易。为了可复现,还要管理好 Nonce,或用 CREATE2 得到确定性的合约地址。

部署成功后,最要紧的是“合约验证”:把源码上传到区块浏览器(Etherscan / Sourcify),让链上字节码与开源源码一一对应,这样路人才能读懂你的逻辑——相当于给店铺挂上“透明厨房”的招牌。多链部署时,同一份脚本切换 network 参数即可,但要逐个核对地址与配置。最后,等待足够多的区块确认让交易“落袋为安”。

剪彩、挂招牌、等确认,三步走完,“无人咖啡店”才算正式开张。但开业只是开始,门一开,监控的探头就得跟着转起来——这正是下一节的主题。

Tconfirm=Nblocks×tblock\displaystyle T_{confirm} = N_{blocks} \times t_{block}
确认时间 = 等待的确认块数 × 平均出块时间。确认的块越多,交易被回滚的概率越低。
  1. 确认块数 N_blocks交易被打包后,后续又产生的新区块数量,代表网络对该交易的“认可程度”。
    NblocksN_{blocks}
  2. 平均出块时间 t_block该链平均每产生一个新区块所需的时间,如以太坊约 12 秒。
    tblockt_{block}
  3. 相乘得确认时间两者相乘得到等待确认的总时长 T_confirm,重要部署通常等待 12~30 个确认。
    Nblocks×tblockN_{blocks} \times t_{block}

部署后运营

开业不是终点,而是营业的开始。无人店里装着监控探头(事件日志),每天打烊后要盘点库存(状态巡检)。合约每发生一次关键动作都会 emit 事件,前端和监控机器人通过监听事件感知链上发生了什么;巡检则定期读取合约的关键状态(余额、暂停标志、owner)与预期比对,发现异常立即告警。

面对“规则不能改”与“出了 bug 怎么办”的矛盾,行业用“代理升级模式”作答:把数据放在代理合约,把逻辑放在可替换的逻辑合约。升级就像翻新后厨而不换店面地址,用户的代币和授权都安然无恙。同时预留 emergencyPause 急停按钮,配合多签钱包,能在攻击发生时先止血、再修复。衡量“店铺”健康度的核心指标是可用率。

一家好店不是开业那天热闹,而是三年后还在稳定营业。智能合约上线后同样如此:事件监控守住“看得见”,状态巡检守住“查得清”,代理升级与急停守住“改得了、停得下”——这套运营闭环,才是合约项目长久生存的护城河。

A=UU+D×100%\displaystyle A = \frac{U}{U + D} \times 100\%
可用率 = 在线时间 ÷(在线时间 + 宕机时间)× 100%。它衡量合约服务持续可用的程度,是运营监控的目标函数。
  1. 在线时间 U统计周期内合约功能正常提供服务的时间长度。
    UU
  2. 宕机时间 D同一周期内因漏洞、攻击或暂停导致服务不可用的时间长度。
    DD
  3. 计算可用率在线时间除以总时间再乘 100%,得到可用率 A,目标是把 D 压到接近零。
    UU+D×100%\frac{U}{U + D} \times 100\%

AI 应用场景

DeFi 借贷协议上线前的自动化测试流水线

阶段:持续集成与自动化测试

解决的问题:传统手工测试需要开发者在本地反复起环境、跑用例,效率低且容易漏分支;一旦合约升级,回归测试要重跑全部,人力成本极高。引入 Foundry + GitHub Actions 后,每次提交代码自动触发模糊测试与全量用例,分钟级产出测试报告。

具体案例:某 DeFi 团队在开发借贷协议时,用 Foundry 编写了 300 多条单元测试和 20 条主网分叉集成测试,PR 合并前必须全部通过且分支覆盖率不低于 85%,否则 CI 直接拦截。上线前还用分叉环境模拟了闪电贷攻击路径,提前修复了一个重入漏洞。

NFT 白名单售卖的多链部署与验证

阶段:部署脚本与源码验证

解决的问题:手工在 Etherscan 上逐个部署合约容易出错,且不同链上的地址不一致会导致用户困惑。通过可复现的部署脚本管理 Nonce 与构造参数,在以太坊、Polygon、Base 上一次性部署,并用自动化脚本统一提交源码验证。

具体案例:某 NFT 项目使用 Hardhat Deploy 编写多链部署脚本,先在各测试网完整预演一遍白名单售卖流程,再向主网广播。部署后自动验证合约源码,并把各链合约地址写入前端配置,用户在官网即可看到“已验证”蓝标。

链上风险监控与异常告警系统

阶段:部署后运营与应急响应

解决的问题:合约上线后无法人工 24 小时盯盘,攻击往往在几分钟内完成。通过监听合约事件与关键状态,结合规则引擎在异常时自动告警,并支持多签触发急停,把损失控制在最小。

具体案例:某稳定币项目部署后接入链上监控机器人,实时监听大额转账、owner 变动、暂停标志变化等事件。某日凌晨预言机报价异常触发告警,运维团队 5 分钟内通过多签执行 emergencyPause,避免了数百万美元级的价格操纵损失。

Python 演示

python104 行
"""智能合约测试与部署的极简模拟(教学版)""" class CoffeeShopContract:    """模拟无人咖啡店的智能合约:开业、买咖啡、暂停营业"""     def __init__(self, owner):        self.owner = owner        self.balance = 0        self.price = 10        self.sold = 0        self.is_open = False        self.is_paused = False     def open_shop(self, caller):        if caller != self.owner:            raise PermissionError("只有店长(owner)可以开业")        self.is_open = True     def emergency_pause(self, caller):        if caller != self.owner:            raise PermissionError("只有店长(owner)可以暂停营业")        self.is_paused = True     def buy_coffee(self, buyer, payment):        if not self.is_open or self.is_paused:            raise RuntimeError("店铺未营业,无法购买")        if payment < self.price:            raise ValueError("余额不足,无法购买")        self.balance += self.price        self.sold += 1        return payment - self.price  class TestReport:    """极简测试报告:记录并统计每个用例的通过情况"""     def __init__(self):        self.cases = []        self.passed = 0        self.failed = 0     def add(self, name, ok, msg):        self.cases.append((name, ok, msg))        if ok:            self.passed += 1        else:            self.failed += 1     def show(self):        print("=" * 46)        for name, ok, msg in self.cases:            tag = "PASS" if ok else "FAIL"            print("{} | {} | {}".format(tag, name, msg))        total = len(self.cases)        rate = self.passed / total * 100        print("用例总数 {},通过 {},失败 {}".format(total, self.passed, self.failed))        print("测试通过率 = {:.1f}%".format(rate))  def run_tests():    report = TestReport()     # 用例1:owner 可以正常开业    shop = CoffeeShopContract(owner="alice")    shop.open_shop("alice")    report.add("open_shop", shop.is_open, "owner 开业成功")     # 用例2:非 owner 不能开业    shop2 = CoffeeShopContract(owner="alice")    try:        shop2.open_shop("bob")        report.add("owner_check", False, "bob 不应开业成功")    except PermissionError:        report.add("owner_check", True, "bob 被正确拒绝")     # 用例3:正常购买并返回找零    change = shop.buy_coffee("bob", 25)    report.add("buy_coffee", change == 15 and shop.sold == 1, "返回找零15且售出1杯")     # 用例4:余额不足应拒绝    try:        shop.buy_coffee("carol", 5)        report.add("insufficient", False, "余额不足不应成交")    except ValueError:        report.add("insufficient", True, "余额不足被正确拒绝")     # 用例5:暂停营业后禁止购买    shop.emergency_pause("alice")    try:        shop.buy_coffee("dave", 20)        report.add("emergency_pause", False, "暂停时不应成交")    except RuntimeError:        report.add("emergency_pause", True, "暂停时购买被正确拒绝")     report.show()    return report  if __name__ == "__main__":    report = run_tests()    if report.failed == 0:        print("所有用例通过,可以准备部署到测试网与主网")    else:        print("存在失败用例,请先修复合约逻辑再部署")
目的:用 Python 模拟一个“无人咖啡店”智能合约,并实现一个极简测试运行器,演示单元测试中“正常路径 + 异常路径 + 通过率统计”的核心思想,与 Solidity 测试一一对应。
  1. class CoffeeShopContract:定义一个模拟合约,相当于 Solidity 里的 contract 声明。
  2. self.is_open = False链上状态变量,合约中的每个状态变更都永久记录。
  3. def open_shop(self, caller):合约中的公共函数,外部用户通过交易调用它。
  4. if caller != self.owner:对应 Solidity 的 require 权限检查,不满足则直接 revert。
  5. report.add("buy_coffee", ...)断言并记录结果,等价于 Hardhat 里的 expect(……).to.equal(……)。
  6. if report.failed == 0:部署前的质量门禁,通过率不达标就不允许上链。

常见误区

误区我在测试网上把所有用例都跑通了,部署到主网肯定没问题,直接复制地址改个网络就跑。

正解测试网与主网规则相近但环境并不相同:依赖的第三方合约可能版本不同、预言机数据来源不同、Gas 价格波动巨大。就像家里试做的咖啡没问题,但开业当天供应商换了咖啡豆、天气变热,口感照样翻车。主网部署前必须核对每个依赖地址、确认非 owner 权限处于锁定状态,并预留应急方案,部署后密切观察前几个区块。

为何常见:测试网与主网使用同一套客户端和语言,极易让人误以为环境等价;实际上外部依赖与市场数据千差万别。

误区合约一部署就是去中心化自治了,不用再管它,反正代码又不会被改。

正解合约不可篡改指的是“逻辑写死”,但线上环境一直在变:预言机喂价异常、闪电贷攻击、新漏洞披露都可能威胁资金安全。就像无人店开业后仍要天天看监控、补货、修机器。行业标配是事件监控、状态巡检、急停与升级机制,运营缺位照样会出大事。

为何常见:把“去中心化、不可篡改”误解为“完全自治、无需运维”,忽略了安全运营才是链上项目的生命线。

误区覆盖率都 100% 了,每条代码都执行过,合约肯定没有 bug,可以放心上线。

正解覆盖率只回答“这些代码行跑过没有”,不回答“结果是否符合业务预期”。就像每道工序都有人试过,不代表配方一定好吃。重入攻击、经济型漏洞往往藏在“代码外的博弈”里,覆盖率、审计、形式化验证、漏洞赏金计划多管齐下才更接近安全。

为何常见:覆盖率数字直观且易得,开发者容易把“测得多”与“测得对”画等号。

误区部署脚本里直接写私钥最省事,反正测试网私钥也不值钱,主网再换一个就好。

正解私钥一旦进入配置文件,就可能随仓库泄露;主网部署时被自动化机器人扫到密钥,资产瞬间归零。行业做法是用环境变量、密码管理器或硬件钱包签名,CI 环境使用密钥管理服务。就像不会把店面钥匙挂在门口,哪怕“只是试营业”也不行。

为何常见:开发阶段图省事,且 Git 仓库的泄露风险被严重低估,一旦入库历史记录里就永远删不干净。

面试题

Q1. 智能合约测试中,测试金字塔自底向上的正确顺序是?

单选题 · easy

  • A.单元测试→集成测试→系统测试← 正确答案
  • B.系统测试→集成测试→单元测试
  • C.集成测试→系统测试→单元测试
  • D.单元测试→系统测试→集成测试

答案:A。测试金字塔强调底座单元测试最多最快、塔尖系统测试最少最慢,自底向上是单元→集成→系统。其他选项颠倒了层级关系,违背“底层数量多、成本低”的原则。

Q2. 单元测试的主要验证对象是?

单选题 · mid

  • A.单个函数的行为与状态变化← 正确答案
  • B.多个合约之间的协作流程
  • C.前端页面与钱包的交互
  • D.矿工打包交易的顺序

答案:A。单元测试针对单个函数,验证返回值、状态变量和事件;多合约协作属于集成测试范畴,前端交互属于系统测试,矿工打包顺序与测试对象无关。

Q3. 下列属于主流智能合约测试框架的是?

多选题 · mid

  • A.Hardhat 与 Foundry← 正确答案
  • B.Remix 与 Truffle← 正确答案
  • C.React 与 Vue.js
  • D.Flask 与 Django

答案:AB。Hardhat、Foundry、Truffle 都是合约开发框架,Remix 是支持测试的浏览器 IDE;React/Vue 是前端框架,Flask/Django 是 Python Web 框架,均不做合约测试。

Q4. 主网分叉(fork)测试的主要用途是?

单选题 · mid

  • A.在真实历史状态上模拟合约交互← 正确答案
  • B.减少主网上的交易手续费
  • C.直接修改已部署合约的逻辑
  • D.提高矿工打包区块的速度

答案:A。主网分叉把主网某个区块的状态克隆到本地,让测试基于真实代币与协议状态进行,风险为零、场景真实。它不改变主网费用、不修改线上合约,也影响不了矿工打包。

Q5. 合约中的 emergencyPause 急停机制主要用于?

单选题 · mid

  • A.发现漏洞时快速停止关键功能← 正确答案
  • B.减少普通用户的转账成本
  • C.提高合约的执行速度
  • D.自动增加代币的流通量

答案:A。急停机制在攻击或漏洞发生时由管理员(常配合多签)一键暂停核心功能,先止血再修复。它不涉及费率、性能或代币发行,是应急响应体系的关键一环。

Q6. 部署后在区块浏览器中验证合约源码的主要作用是?

单选题 · hard

  • A.让字节码与开源源码对应可查← 正确答案
  • B.降低部署时的 Gas 消耗
  • C.修改合约中的业务规则
  • D.让矿工优先打包该合约交易

答案:A。合约验证把源码与链上字节码做匹配并公开,用户可自行核对逻辑,提升可信度。它不改变已部署代码,与 Gas、矿工优先级完全无关。

Q7. 关于测试网与主网的区别,正确的是?

单选题 · easy

  • A.测试网代币没有真实经济价值← 正确答案
  • B.测试网无法执行智能合约
  • C.主网部署不需要消耗 Gas
  • D.主网合约可以随时修改

答案:A。测试网代币来自水龙头、无真实价值,适合低成本演练;测试网同样能执行合约,主网部署必须付 Gas,且主网合约一旦部署便不可修改。

Q8. 合约上线前的合理检查项包括?

多选题 · hard

  • A.进行代码审计与权限核查← 正确答案
  • B.在测试网完成全流程演练← 正确答案
  • C.预估部署与调用的 Gas 成本← 正确答案
  • D.把私钥直接写入部署脚本

答案:ABC。审计、权限核查、测试网演练、成本预估都是部署清单标准项;把私钥写进脚本是最危险的反模式,密钥一旦入库就可能被扫走导致资产归零。

Q9. 代理升级模式(Proxy)的主要优点是?

单选题 · mid

  • A.保留合约地址的同时更新逻辑← 正确答案
  • B.删除链上全部历史交易记录
  • C.让部署合约完全免费
  • D.跳过矿工的交易验证流程

答案:A。代理模式把数据留在代理合约、逻辑放在可替换的逻辑合约,用户地址不变就能升级业务逻辑,相当于翻新后厨不换店面。它不能删除链上记录、不能免 Gas、更不能绕过共识验证。

Q10. 估算合约部署与调用成本时,需要考虑?

多选题 · extreme

  • A.部署交易所消耗的 Gas 数量← 正确答案
  • B.每次调用所消耗的 Gas 数量← 正确答案
  • C.当前网络环境的 Gas 价格← 正确答案
  • D.合约源码中注释的字符数量

答案:ABC。总成本 = 消耗的 Gas 数量 × Gas 单价,部署与调用各自消耗的 Gas 加上网络动态价格共同决定成本;源码注释不参与编译,不影响 EVM 执行,与成本无关。