/// Handler interface.
/// Handler defines business related functions.
/// Use the interface to ensure that your external services are always supported.
/// Because of function live(), we design IHandler as an abstract contract rather than a true interface.
// Handler 接口。
// Handler 定义了与业务相关的功能。
// 使用该接口以确保始终支持您的外部服务。
// 由于函数 live() 的存在,我们将 IHandler 设计为抽象合约而不是真正的接口。
contractIHandler{/// Initialize the data contarct.
/// @param _str value of exmStr of Data contract.
/// @param _int value of exmInt of Data contract.
/// @param _array value of exmArray of Data contract.
// 初始化数据合约。
// @param _str Data 合约中 exmStr 的值。
// @param _int Data 合约中 exmInt 的值。
// @param _array Data 合约中 exmArray 的值。
functioninitialize(string_str,uint256_int,uint16[]_array)public;/// Register Upgrader contract address.
/// @param _upgraderAddr address of the Upgrader contract.
// 注册 Upgrader 合约地址。
// @param _upgraderAddr Upgrader 合约的地址。
functionregisterUpgrader(address_upgraderAddr)external;/// Upgrader contract calls this to check if it is registered.
/// @return if the Upgrader contract is registered.
// Upgrader 合约调用此函数以检查它是否已注册。
// @return 如果 Upgrader 合约已注册。
functionisUpgraderRegistered()externalviewreturns(bool);/// Handler has been upgraded so the original one has to self-destruct.
// Handler 已被升级,因此原始 Handler 必须自毁。
functiondone()external;/// Check if the Handler contract is a working Handler contract.
/// It is used to prove the contract is a Handler contract.
/// @return always true.
// 检查 Handler 合约是否是正在工作的 Handler 合约。
// 它用于证明该合约是 Handler 合约。
// @return 总是 true。
functionlive()externalpurereturns(bool){returntrue;}/** Functions - define functions here *//** 函数 - 在此处定义函数 *//** Events - add events here *//** 事件 - 在此处添加事件 */}
部署 Handler 合约的过程:
部署 Data 合约;
在 Data 合约中指定的给定地址部署 Handler 合约;
通过调用 Data 合约中的 setHandler() 来注册 Handler 合约地址,或者使用 Upgrader 合约来切换 Handler 合约,这要求 Data 合约已初始化;
/// Data Contract
// 数据合约
contractDataContract{/** Management data *//** 管理数据 *//// Owner and Handler contract
// 所有者和 Handler 合约
addressprivateowner;addressprivatehandlerAddr;/// Ready?
// 准备好了吗?
boolprivatevalid;/** Upgrader data *//** Upgrader 数据 */addressprivateupgraderAddr;uint256privateproposalBlockNumber;uint256privateproposalPeriod;/// Upgrading status of the Handler contract
// Handler 合约的升级状态
enumUpgradingStatus{/// Can be upgraded
// 可以升级
Done,/// In upgrading
// 升级中
InProgress,/// Another proposal is in progress
// 另一个提案正在进行中
Blocked,/// Expired
// 已过期
Expired,/// Original Handler contract error
// 原始 Handler 合约错误
Error}/** Data resources - define variables here *//** 数据资源 - 在此处定义变量 *//** Modifiers *//** 修饰器 *//// Check if msg.sender is the Handler contract. It is used for setters.
/// If fail, throw PermissionException.
// 检查 msg.sender 是否是 Handler 合约。它用于 setter。
// 如果失败,则抛出 PermissionException。
modifieronlyHandler;/// Check if msg.sender is not permitted to call getters. It is used for getters (if necessary).
/// If fail, throw GetterPermissionException.
// 检查是否允许 msg.sender 调用 getter。它用于 getter(如果需要)。
// 如果失败,则抛出 GetterPermissionException。
modifierallowedAddress;/// Check if the contract is working.
/// It is used for all functions providing services after initialization.
/// If fail, throw UninitializationException.
// 检查合约是否正在工作。
// 它用于初始化后提供服务的所有函数。
// 如果失败,则抛出 UninitializationException。
modifierready;/** Management functions *//** 管理功能 *//// Initializer. Just the Handler contract can call it.
/// @param _str default value of this.exmStr.
/// @param _int default value of this.exmInt.
/// @param _array default value of this.exmArray.
/// exception PermissionException msg.sender is not the Handler contract.
/// exception ReInitializationException contract has been initialized.
/// @return if the initialization succeeds.
// 初始化器。只有 Handler 合约可以调用它。
// @param _str this.exmStr 的默认值。
// @param _int this.exmInt 的默认值。
// @param _array this.exmArray 的默认值。
// exception PermissionException msg.sender 不是 Handler 合约。
// exception ReInitializationException 合约已初始化。
// @return 如果初始化成功。
functioninitialize(string_str,uint256_int,uint16[]_array)externalonlyHandlerreturns(bool);/// Set Handler contract for the contract. Owner must set one to initialize the Data contract.
/// Handler can be set by owner or Upgrader contract.
/// @param _handlerAddr address of a deployed Handler contract.
/// @param _originalHandlerAddr address of the original Handler contract, only used when an Upgrader contract want to set the Handler contract.
/// exception PermissionException msg.sender is not the owner nor a registered Upgrader contract.
/// exception UpgraderException Upgrader contract does not provide a right address of the original Handler contract.
/// @return if Handler contract is successfully set.
// 为合约设置 Handler 合约。所有者必须设置一个才能初始化 Data 合约。
// Handler 可以由所有者或 Upgrader 合约设置。
// @param _handlerAddr 已部署的 Handler 合约的地址。
// @param _originalHandlerAddr 原始 Handler 合约的地址,仅当 Upgrader 合约要设置 Handler 合约时才使用。
// exception PermissionException msg.sender 不是所有者也不是已注册的 Upgrader 合约。
// exception UpgraderException Upgrader 合约未提供原始 Handler 合约的正确地址。
// @return 如果 Handler 合约已成功设置。
functionsetHandler(address_handlerAddr,address_originalHandlerAddr)externalreturns(bool);/** Upgrader contract functions *//** Upgrader 合约功能 *//// Register an Upgrader contract in the contract.
/// If a proposal has not been accepted until proposalBlockNumber + proposalPeriod, it can be replaced by a new one.
/// @param _upgraderAddr address of a deployed Upgrader contract.
/// exception PermissionException msg.sender is not the owner.
/// exception UpgraderConflictException Another Upgrader contract is working.
/// @return if Upgrader contract is successfully registered.
// 在合约中注册 Upgrader 合约。
// 如果在 proposalBlockNumber + proposalPeriod 之前未接受提案,则可以将其替换为新提案。
// @param _upgraderAddr 已部署的 Upgrader 合约的地址。
// exception PermissionException msg.sender 不是所有者。
// exception UpgraderConflictException 另一个 upgrader 正在工作。
// @return 如果 Upgrader 合约已成功注册。
functionstartUpgrading(address_upgraderAddr)publicreturns(bool);/// Getter of proposalPeriod.
/// exception UninitializationException uninitialized contract.
/// exception GetterPermissionException msg.sender is not permitted to call the getter.
/// @return this.proposalPeriod.
// proposalPeriod 的 Getter。
// exception UninitializationException 未初始化的合约。
// exception GetterPermissionException 不允许 msg.sender 调用 getter。
// @return this.proposalPeriod。
functiongetProposalPeriod()publicviewisReadyallowedAddressreturns(uint256);/// Setter of proposalPeriod.
/// @param _proposalPeriod new value of this.proposalPeriod.
/// exception UninitializationException uninitialized contract.
/// exception PermissionException msg.sender is not the owner.
/// @return if this.proposalPeriod is successfully set.
// proposalPeriod 的 Setter。
// @param _proposalPeriod this.proposalPeriod 的新值。
// exception UninitializationException 未初始化的合约。
// exception PermissionException msg.sender 不是所有者。
// @return 如果 this.proposalPeriod 已成功设置。
functionsetProposalPeriod(uint256_proposalPeriod)publicisReadyreturns(bool);/// Return upgrading status for Upgrader contracts.
/// @param _originalHandlerAddr address of the original Handler contract.
/// exception UninitializationException uninitialized contract.
/// @return Handler contract's upgrading status.
// 返回 Upgrader 合约的升级状态。
// @param _originalHandlerAddr 原始 Handler 合约的地址。
// exception UninitializationException 未初始化的合约。
// @return Handler 合约的升级状态。
functioncanBeUpgraded(address_originalHandlerAddr)externalviewisReadyreturns(UpgradingStatus);/// Check if the contract has been initialized.
/// @return if the contract has been initialized.
// 检查合约是否已初始化。
// @return 如果合约已初始化。
functionlive()externalviewreturns(bool);/** Getters and setters of data resources: define functions here *//** 数据资源的 Getter 和 Setter:在此处定义函数 */}
Upgrader 合约(可选)
可以通过调用 Data 合约的 setHandler() 来升级 Handler 合约。如果所有者想从用户那里收集想法,则 Upgrader 合约将帮助他/她管理投票和升级。
以下是 Upgrader 合约的规范:
Upgrader 合约具有从已注册的投票者那里获得投票的能力。
合约所有者可以在提案到期前的任何时间添加投票者;
投票者可以检查提案的当前状态(成功或已过期)。
开发人员可以通过在部署后随时调用 done() 来删除此 Upgrader 合约。
Upgrader 合约的工作方式如下:
验证 Data 合约,其对应的 Handler 合约和新的 Handler 合约都已部署;
使用 Data 合约地址,先前的 Handler 合约地址和新的 Handler 合约地址来部署 Upgrader 合约;
首先在新 Handler 合约中注册 upgrader 地址,然后注册原始 handler,最后注册 Data 合约;
调用 startProposal() 以启动投票过程;
在到期前调用 getResolution();
升级成功或提案已过期。
注意:
可以随时调用函数 done(),以使 upgrader 自行销毁。
可以随时调用函数 status(),以显示 upgrader 的调用者状态。
/// Handler upgrader
// Handler 升级器
contractUpgrader{// Data contract
// 数据合约
DataContractpublicdata;// Original Handler contract
// 原始 Handler 合约
IHandlerpublicoriginalHandler;// New Handler contract
// 新的 Handler 合约
addresspublicnewHandlerAddr;/** Marker *//** 标记 */enumUpgraderStatus{Preparing,Voting,Success,Expired,End}UpgraderStatuspublicstatus;/// Check if the proposal is expired.
/// If so, contract would be marked as expired.
/// exception PreparingUpgraderException proposal has not been started.
/// exception ReupgradingException upgrading has been done.
/// exception ExpirationException proposal is expired.
// 检查提案是否已过期。
// 如果是这样,合约将被标记为已过期。
// exception PreparingUpgraderException 提案尚未启动。
// exception ReupgradingException 已完成升级。
// exception ExpirationException 提案已过期。
modifiernotExpired{require(status!=UpgraderStatus.Preparing,"Invalid proposal!");require(status!=UpgraderStatus.Success,"Upgrading has been done!");require(status!=UpgraderStatus.Expired,"Proposal is expired!");if(data.canBeUpgraded(address(originalHandler))!=DataContract.UpgradingStatus.InProgress){status=UpgraderStatus.Expired;require(false,"Proposal is expired!");}_;}/// Start voting.
/// Upgrader must do upgrading check, namely checking if Data contract and 2 Handler contracts are ok.
/// exception RestartingException proposal has been already started.
/// exception PermissionException msg.sender is not the owner.
/// exception UpgraderConflictException another upgrader is working.
/// exception NoPreparationException original or new Handler contract is not prepared.
// 开始投票。
// Upgrader 必须进行升级检查,即检查 Data 合约和 2 个 Handler 合约是否正常。
// exception RestartingException 提案已经开始。
// exception PermissionException msg.sender 不是所有者。
// exception UpgraderConflictException 另一个 upgrader 正在工作。
// exception NoPreparationException 原始或新的 Handler 合约未准备好。
functionstartProposal()external;/// Anyone can try to get resolution.
/// If voters get consensus, upgrade the Handler contract.
/// If expired, self-destruct.
/// Otherwise, do nothing.
/// exception PreparingUpgraderException proposal has not been started.
/// exception ExpirationException proposal is expired.
/// @return status of proposal.
// 任何人都可以尝试获得解决方案。
// 如果投票者达成共识,则升级 Handler 合约。
// 如果过期,则自毁。
// 否则,不执行任何操作。
// exception PreparingUpgraderException 提案尚未启动。
// exception ExpirationException 提案已过期。
// @return 提案的状态。
functiongetResolution()externalreturns(UpgraderStatus);/// Destruct itself.
/// exception PermissionException msg.sender is not the owner.
// 自行销毁。
// exception PermissionException msg.sender 不是所有者。
functiondone()external;/** Other voting mechanism related variables and functions *//** 其他与投票机制相关的变量和函数 */}
尽管升级合约可能需要一些努力和 gas,但它比弃用不安全的合约/创建新合约或硬分叉(例如 DAO 攻击)要容易得多。合约创建需要大量的精力和 gas。可升级合约的优势之一是合约所有者不必创建新合约;相反,他们只需要升级导致问题的合约部分,与数据丢失和区块链不一致相比,这便宜得多。换句话说,可升级合约使 Data 合约更具可扩展性和灵活性。