智能合约的不可更改性
前面的内容里,Solidity 和其他开发语言没有特别大的区别,接下来我们要说的智能合约的一个非常大的特性:**不可更改性**。
在我们把智能合约部署到智能合约平台(比如以太坊)之后,它就变得 不可更改, 这种不可更改意味着你的代码不能被调整或更新。你的智能合约程序会不可更改地存在智能合约平台上。
这是智能合约的优势:一旦函数被定义下来,每一次的运行,程序都会严格遵照函数中原有的代码逻辑一丝不苟地执行,完全不用担心程序被人篡改而得到意外的结果。
这也会带来非常大的安全挑战,如果我们的智能程序有任何漏洞,在部署后即使你发现了也无法补救。我们没办法通过软件升级或者打补丁的方式替换程序。
所以在这种情况下 Solidity 代码的安全性就变得极其重要。如果你的智能合约有任何漏洞,只能让用户们放弃这个智能合约,然后转移到一个新的修复后的合约上。
在我们的智能合约有一些外部依赖关系时,我们也最好不要采用硬编码的方式来处理,最好是配置成“函数”来获得相应的值,以便必要时的修改。
外部依赖的处理
在前面的内容里,我们将加密小猫(CryptoKitties)合约的地址硬编码到智能合约中去了。
这会带来一个问题:如果加密小猫地址失效了,我们的智能合约也会随之失效 -- 因为我们在代码中用“硬编码”的方式指定了加密小猫的地址,如果这个根据地址找不到小猫,我们的区块宠物也就无法和小猫配对了,而由于智能合约的 **不可更改性**,我们却没法修改合约去应付这个问题!
因此,我们不能对合约地址采用硬编码的方式,而应该采用“函数”来获得合约地址,那样在出现必要的情况时,我们可以以参数的形式进行修改。
我们不再一开始就把地址给写入代码,而是写个函数 setKittyContractAddress, 运行时再设定合约的地址,不用担心加密小猫的地址失效问题。
实战演习
请修改之前的代码,使得可以通过程序更改 CryptoKitties 合约地址。
删除采用硬编码方式的 ckAddress 代码行。
之前创建 kittyContract 变量的那行代码,修改为对 kittyContract 变量的声明 -- 暂时不给它指定具体的实例。
创建名为 setKittyContractAddress 的函数, 它带一个参数 _address(address类型), 可见性设为external。
在setKittyContractAddress 函数内部,添加一行代码,将 kittyContract 变量赋值为:KittyInterface(_address)。
注意:你可能会注意到这个功能有个安全漏洞,我们到下一步会解决它


