考虑升级问题
Code is law,智能合约就是写在区块链上自动执行的法律,目前以太坊上的智能合约还不具有升级功能,一旦部署成功便无法修改代码逻辑。大家似乎普遍都接受这一点,但在实际业务开发,很难说一开始就能考虑到所有问题,上线后往往需要对核心逻辑进行升级迭代。就拿很多STO项目来说,代币合约代码内的核心是转账限制,考虑的因素有锁仓时间,黑白名单,权限等。在未来很可能对规则进行修改,那就需要设计一套可升级的合约结构。
可行性
首先,solidity语言提供了call
和delegatecall
函数用于外部调用其他合约。考虑模块化的设计思路,在层级上分为入口层,控制逻辑的实现层,数据状态的读写层。一般的代币合约都是在同一个智能合约中实现了这三个层级,我们考虑将其拆分成三个合约:对用户来说,感知到的只有入口层,入口层地址对应普通代币合约的合约地址,使用到的函数一般也是ERC20标准定义的函数及拓展,这些确实不会发送变动。然后提供一个数据层合约,里面存放代币的总量,各个账户的余额,地址之间的授权额度,还有代币的基本信息,根据具体需求提供getter和setter。再准备一个逻辑层合约,暴露供入口层调用的标准接口函数,并实现具体逻辑,同时逻辑层调用会数据层提供的getter和setter来进行数据的读写。这三个合约之间挂上钩子,避免任何人都能调用。这是典型的MVC模式,一般入口层和数据层都不应该升级,需要升级更新的是逻辑层,每次升级重新挂好钩子即可。
实现示例
如图,用户调用入口层合约中满足ERC20接口的函数,这些函数再外部调用逻辑层合约中满足ILogic接口的函数,然后这些函数又会外部调用数据层合约中满足Getter/Setter定义的读写函数。数据层合约中存储基本的状态,逻辑层合约中存储控制相关的状态。三个合约之间通过钩子连接,每个合约必须由管理员更改钩子。
GFT是一个典型的ST合约,这里是具体的实现代码: