该提案介绍了EigenLayer的奖励机制的第二次迭代(v2),旨在增强EigenLayer生态系统中奖励的灵活性。Rewards v2的主要功能包括:AVS根据operator表现定向奖励;AVS奖励的可变operator费用;专门用于Programmatic Incentives的operator拆分;以及方便staker和operator批量申领奖励。
作者 | Matt Nelson, Rajath Alex, Scott Conner, Sean McGary |
---|---|
创建日期 | 2024 年 10 月 18 日 |
状态 | 已合并 |
参考资料 | EigenLayer 协议 PR EigenLayer 中间件 PR EigenLayer Sidecar PR |
讨论 | 论坛帖子 |
本提案介绍了 EigenLayer 奖励(v2) 的迭代,这是一项旨在增强 EigenLayer 生态系统中奖励灵活性的升级。在发布奖励的第一次迭代之后,通过来自 AVS 和 Operator 的反馈,我们建议扩展平台奖励功能。奖励 v2 是对奖励结构和合约的轻量级补充,解决了关键的奖励用例:
总而言之,这些变更将有助于在生态系统中实现广泛的灵活性:更多的 AVS 可以奖励 Operator,更多的 Operator 可以运行具有可变费率的不同 AVS,并且 Staker 将拥有数据来发现哪些服务和安全形式是 AVS 所重视的。
奖励 v2 解决了 EigenLayer 奖励 MVP(v1)中发现的关键挑战,特别是需要通过外部逻辑进行 Operator 定向奖励,以及 Operator 在设置不同费率方面的灵活性,以便更好地覆盖运营成本或在运行不同 AVS 类型时吸引更多 stake。AVS 对更多基于绩效的奖励的需求不断增长,促使了这项新提案,确保 EigenLayer 的奖励协议能够服务于更广泛的场景。
在与 AVS 讨论之后,本提案旨在快速迭代 EigenLayer 奖励,以服务于以下用例:
以上迭代将使奖励从 AVS 流向 Operator 的方式更加灵活。
AVS 一直在寻找向 EigenLayer 协议管理的 token 生命周期添加额外激励功能的方法,例如 Staker 定向奖励。此功能不在本提案的范围之内。
奖励 v2 旨在成为奖励 MVP(v1)的 可选 和附加升级,具有以下属性:
AVS 的外部奖励计算逻辑:
AVS 和 Operator 基础设施的灵活性:
更便宜的批量领取:
利用现有基础设施:
RewardsCoordinator
合约将被升级以支持基于绩效的奖励分配、设置每个 AVS 的 Operator 费用和批量申领的功能。奖励归属
无需许可的可验证性:
防止奖励分配树膨胀:
启用程序化激励:
本文档中的关键词“必须”、“不得”、“必需”、“应”、“不应”、“应该”、“不应该”、“推荐”、“可以”和“可选”应按照 RFC 2119 中的描述进行解释。
高级流程如下:
RewardsCoordinator
上的 setOperatorAVSSplit()
来设置其每个 AVS 的奖励费用(称为“split”)。这介于 AVS 奖励的 0% 或 100% 之间。在 7 天的激活延迟后才有效。如果他们不设置,它将保持在默认的 10%。一个 Operator 一次只能有一个待处理的 split 配置。AVSServiceManager
上调用 createOperatorDirectedAVSRewardsSubmission()
,该调用将调用代理到 RewardsCoordinator
。这将启动基于绩效的奖励分配,并将所有 Operator 奖励的总和存入 RewardsCoordinator
的分配中。OperatorDirectedAVSRewardsSubmissionCreated
事件。OperatorDirectedAVSRewardsSubmissionCreated
事件并存储它。RewardsCoordinator
上的 submitRoot()
每周发布该根。RewardsCoordinator
合约上的 processClaims()
来批量领取他们所有的奖励。有关 Sidecar 的更多详细信息,请参见下文。
RewardsCoordinator
透明代理将升级为指向包含以下逻辑的新实现。
该设计主要建立在现有的奖励 v1 接口之上,并带有额外的字段,这些字段:
AVS 可以自由地在奖励归属逻辑中使用链上或链下数据来确定每个 Operator 的奖励金额。这可以根据 Operator 在特定时间段内执行的工作进行自定义,可以是统一的奖励率,也可以是基于 AVS 经济模型的其他结构。这将使 AVS 能够灵活地奖励不同 Operator 的绩效和其他变量,同时为委托给同一 Operator 和 strategy 的 Staker 保持相同的易于计算的奖励率。AVS 可以提交以不同 token 计价的多个基于绩效的奖励,以获得更大的灵活性。
可以在下面找到 RewardsCoordinator
中 Operator 定向奖励的接口。
/**
* @notice Strategies 和乘数的线性组合,供 AVS 加权 EigenLayer strategies。
* @param strategy 要用于奖励 submission 的 EigenLayer strategy。
* @param multiplier 奖励 submission 中 strategy 的权重。
*/
struct StrategyAndMultiplier {
IStrategy strategy;
uint96 multiplier;
}
/**
* @notice Operator 的奖励结构体
* @param operator 要奖励的 Operator
* @param amount Operator 的奖励金额
*/
struct OperatorReward {
address operator;
uint256 amount;
}
/**
* @notice OperatorDirectedRewardsSubmission 结构体,由 AVS 在为其 Operator 和 staker 制定 Operator 定向奖励时提交。
* @param strategiesAndMultipliers strategies 及其相对权重。
* @param token 要分配的奖励 token。
* @param operatorRewards Operator 的奖励。
* @param startTimestamp 考虑用于分配的 submission 范围的时间戳(秒)。
* @param duration submission 范围的持续时间,以秒为单位。
* @param description 描述奖励 submission 的用途。
*/
struct OperatorDirectedRewardsSubmission {
StrategyAndMultiplier[] strategiesAndMultipliers;
IERC20 token;
OperatorReward[] operatorRewards;
uint32 startTimestamp;
uint32 duration;
string description;
}
/**
* @notice 当 AVS 创建有效的 `OperatorDirectedRewardsSubmission` 时发出
* @param caller 调用 `createOperatorDirectedAVSRewardsSubmission` 的地址。
* @param avs 代表其提交 Operator 定向奖励的 avs。
* @param operatorDirectedRewardsSubmissionHash (`avs`、`submissionNonce` 和 `operatorDirectedRewardsSubmission`) 的 Keccak256 哈希。
* @param submissionNonce avs 的当前 nonce。用于生成唯一的 submission 哈希。
* @param operatorDirectedRewardsSubmission Operator 定向奖励 Submission。包含 token、开始时间戳、持续时间、Operator 奖励、描述以及 strategy 和乘数。
*/
event OperatorDirectedAVSRewardsSubmissionCreated(
address indexed caller,
address indexed avs,
bytes32 indexed operatorDirectedRewardsSubmissionHash,
uint256 submissionNonce,
OperatorDirectedRewardsSubmission
);
/**
* @notice 代表 AVS 创建一个新的 Operator 定向奖励 submission,以在注册到 `avs` 的 Operator 和委托给 Operator 的 staker 集合之间进行 split。
* @param avs 代表其提交奖励的 AVS。
* @param operatorDirectedRewardsSubmissions 要创建的 Operator 定向奖励 submissions。
*/
function createOperatorDirectedAVSRewardsSubmission(
address avs,
OperatorDirectedRewardsSubmission[] calldata operatorDirectedRewardsSubmissions
) external;
avs
调用(它具有前瞻性,可以由 avs 委托地址调用)。需要进行 msg.sender == avs
检查。如果检查失败,则抛出错误。operatorDirectedRewardsSubmissions
:
strategiesAndMultipliers
数组的长度为 0,则抛出错误。这些是必需的。operatorRewards
数组的长度为 0,则抛出错误。这些是必需的。operatorReward
,验证以下各项:
operator
为 address(0)
,则抛出错误。amount
为 0,则抛出错误。MAX_REWARDS_AMOUNT
。否则抛出错误。duration
必须 <= MAX_REWARDS_DURATION
。否则抛出错误。duration
必须是 CALCULATION_INTERVAL_SECONDS
的倍数。否则抛出错误。startTimestamp
必须是 CALCULATION_INTERVAL_SECONDS
的倍数。否则抛出错误。startTimestamp
必须 > GENESIS_REWARDS_TIMESTAMP
。否则抛出错误。startTimestamp
必须在 block.timestamp
之前的 MAX_RETROACTIVE_LENGTH
内。否则抛出错误。startTimestamp + duration
必须 < block.timestamp
。否则抛出错误。基于绩效的奖励必须是严格的追溯性奖励。strategyAndMultiplier
,验证以下各项:
strategy
必须在存款的白名单中。否则抛出错误。avs
、submissionNonce
和 operatorDirectedRewardsSubmission
的 ABI 编码。RewardsCoordinator
合约中。OperatorDirectedAVSRewardsSubmissionCreated
事件。avs
当前是相应的 AVSServiceManager
。createOperatorDirectedAVSRewardsSubmission
之前,RewardsCoordinator
合约需要 operatorDirectedRewardsSubmissions
中所有 operatorRewards
总和的 token 批准。createOperatorDirectedAVSRewardsSubmission
函数主要只是进行链上验证,将奖励总额存入 RewardsCoordinator
合约中并发出事件。createOperatorDirectedAVSRewardsSubmission()
都会奖励每个 operator
及其 Staker 在 startTimestamp
之后的 duration
内 amount
的 token
,代表 avs
。 Operator 将获得其合约配置的奖励 split,该奖励在 RewardsCoordinator
中设置,其余部分将按比例分配给 strategies 和乘数。在奖励 v2 上线后,Operator 将能够在 RewardsCoordinator
中更改其每个 AVS 粒度的税后费用。在 7 天的激活延迟后才有效,以便 Staker 有时间根据新的抽取率调整其 Operator 服务提供商。如果他们不设置每个 AVS 奖励 split,它将默认为 10%。
此可变费用在 AVS 支付的奖励的 0% 到 100% 之间没有对其价值的约束。AVS 仍然可以通过在 AVS 目录合约上调用 deregisterOperatorFromAVS() 来选择驱逐他们认为以恶意行事的 Operator。我们希望 AVS 和 Operator 能够进行讨论,以发现不同类型的 AVS 的正确动态。
可以在下面找到 RewardsCoordinator
中可变 Operator Split 接口。
/**
* @notice Operator 的 split 结构体
* @param oldSplitBips 以基点表示的旧 split。如果 `block.timestamp < activatedAt`,则此 split 处于活动状态
* @param newSplitBips 以基点表示的新 split。如果 `block.timestamp >= activatedAt`,则此 split 处于活动状态
* @param activatedAt split 将被激活的时间戳
*/
struct OperatorSplit {
uint16 oldSplitBips;
uint16 newSplitBips;
uint32 activatedAt;
}
/**
* @notice 当设置 AVS 的 Operator split 时发出。
* @param caller 调用 `setOperatorAVSSplit` 的地址。
* @param operator 代表其设置 split 的 Operator。
* @param avs Operator 为其设置 split 的 avs。
* @param activatedAt split 将被激活的时间戳。
* @param oldOperatorAVSSplitBips Operator 的 AVS 旧 split。
* @param newOperatorAVSSplitBips Operator 的 AVS 新 split。
*/
event OperatorAVSSplitBipsSet(
address indexed caller,
address indexed operator,
address indexed avs,
uint32 activatedAt,
uint16 oldOperatorAVSSplitBips,
uint16 newOperatorAVSSplitBips
);
/**
* @notice 设置特定 Operator 的特定 avs 的 split。
* @param operator 设置 split 的 Operator。
* @param avs Operator 为其设置 split 的 avs。
* @param split Operator 的特定 avs 的 split。
*/
function setOperatorAVSSplit(address operator, address avs, uint16 split) external;
/// @notice 特定 `operator` 的特定 `avs` 的 split
function getOperatorAVSSplit(address operator, address avs) external view returns (uint16);
setOperatorAVSSplit()
必须包括所有字段;没有一个是可选的。operator
调用(它具有前瞻性,可以由 Operator 委托地址调用)。需要进行 msg.sender == operator
检查。如果检查失败,则抛出错误。split
严格大于 10000
(即 100%),则抛出错误。operator
和 avs
的更早 split 尚未激活,则抛出错误。setOperatorAVSSplit()
都会代表 operator
设置 avs
的 split
(以基点为单位)。split
将在 7 天的激活延迟后激活。OperatorAVSSplitBipsSet
事件。Eigen Foundation 程序化激励的默认 Operator split 为 10%,可变 split 旨在确保所有规模和 stake 的 Operator 都能因其参与而获得奖励。在 7 天的激活延迟后才有效。它可以独立于其他 AVS 进行设置,并且具有与 v2 奖励相同的 Operator 委托 Staker 的奖励分配动态。
可以在下面找到 RewardsCoordinator
中用于程序化激励的 Operator Split 接口。
/**
* @notice Operator 的 split 结构体
* @param oldSplitBips 以基点表示的旧 split。如果 `block.timestamp < activatedAt`,则此 split 处于活动状态
* @param newSplitBips 以基点表示的新 split。如果 `block.timestamp >= activatedAt`,则此 split 处于活动状态
* @param activatedAt split 将被激活的时间戳
*/
struct OperatorSplit {
uint16 oldSplitBips;
uint16 newSplitBips;
uint32 activatedAt;
}
/**
* @notice 当设置程序化激励的 Operator split 时发出。
* @param caller 调用 `setOperatorPISplit` 的地址。
* @param operator 代表其设置 split 的 Operator。
* @param activatedAt split 将被激活的时间戳。
* @param oldOperatorPISplitBips Operator 的程序化激励的旧 split。
* @param newOperatorPISplitBips Operator 的程序化激励的新 split。
*/
event OperatorPISplitBipsSet(
address indexed caller,
address indexed operator,
uint32 activatedAt,
uint16 oldOperatorPISplitBips,
uint16 newOperatorPISplitBips
);
/**
* @notice 设置特定 Operator 的程序化激励的 split。
* @param operator 代表其设置 split 的 Operator。
* @param split Operator 的程序化激励的 split。
*/
function setOperatorPISplit(address operator, uint16 split) external;
/// @notice 特定 `operator` 的程序化激励的 split
function getOperatorPISplit(address operator) external view returns (uint16);
setOperatorPISplit()
必须包括所有字段;没有一个是可选的。operator
调用(它具有前瞻性,可以由 Operator 委托地址调用)。需要进行 msg.sender == operator
检查。如果检查失败,则抛出错误。split
严格大于 10000
(即 100%),则抛出错误。operator
的更早 split 尚未激活,则抛出错误。setOperatorPISplit()
都会代表 operator
设置程序化激励的 split
(以基点为单位)。split
将在 7 天的激活延迟后激活。OperatorPISplitBipsSet
事件。为了实现 gas 高效的申领方式,奖励 v2 还提供了一个用于批量申领的新接口(即 processClaims()
)。v1 接口(即 processClaim()
)仍然可用。目前,我们仅支持每个单个赚取者进行申领。此接口提供了一种将多个赚取者的申领批量化为单个交易的方法。
可以在下面找到 RewardsCoordinator
中的批量奖励申领接口。
/**
* @notice 赚取者帐户叶子的 Merkle 树中的内部叶子。
* @param earner 赚取者的地址。
* @param earnerTokenRoot 赚取者 token 子树的 Merkle 根。
*/
struct EarnerTreeMerkleLeaf {
address earner;
bytes32 earnerTokenRoot;
}
/**
* @notice 分配 Merkle 树中的实际叶子,指定各个赚取者的子树的 token 收益。
* @param token 要申领收益的 ERC20 token。
* @param cumulativeEarnings 赚取者的 token 的累积收益。
*/
struct TokenTreeMerkleLeaf {
IERC20 token;
uint256 cumulativeEarnings;
}
/**
* @notice 针对分配根的申领。
* @param rootIndex DistributionRoots 列表中根的索引。
* @param earnerIndex Merkle 树中赚取者帐户根的索引。
* @param earnerTreeProof 针对 Merkle 根的赚取者的 EarnerTreeMerkleLeaf 的证明。
* @param earnerLeaf 赚取者的 EarnerTreeMerkleLeaf 结构体,提供赚取者地址和 earnerTokenRoot
* @param tokenIndices 赚取者子树中 token 叶子的索引
* @param tokenTreeProofs 针对赚取者的 earnerTokenRoot 的 token 叶子的证明
* @param tokenLeaves 要申领的 token 叶子。
*/
struct RewardsMerkleClaim {
uint32 rootIndex;
uint32 earnerIndex;
bytes earnerTreeProof;
EarnerTreeMerkleLeaf earnerLeaf;
uint32[] tokenIndices;
bytes[] tokenTreeProofs;
TokenTreeMerkleLeaf[] tokenLeaves;
}
/**
* @notice 当针对 distribution 根申领赚取者奖励时发出。
* @param root 被申领的 distribution 根。
* @param earner 代表其申领奖励的赚取者。
* @param claimer 奖励的申领者。
* @param recipient 接收 ERC20 奖励的地址。
* @param token 要申领收益的 ERC20 token。
* @param claimedAmount 被申领的金额。
*/
event RewardsClaimed(
bytes32 root,
address indexed earner,
address indexed claimer,
address indexed recipient,
IERC20 token,
uint256 claimedAmount
);
/**
* @notice 针对给定的 distribution 根批量申领奖励。
* @param claims 要处理的 RewardsMerkleClaims。包含根索引、赚取者、token 叶子和所需的证明
* @param recipient 接收 ERC20 奖励的地址。
*/
function processClaims(RewardsMerkleClaim[] calldata claims, address recipient) external;
processClaims()
必须包括所有字段;没有一个是可选的。processClaim()
外部函数中的所有逻辑都将重构为新的 _processClaim()
内部函数。processClaim()
将调用 _processClaim()
。这保持了 processClaim()
的现有接口不变。processClaims()
只能由有效的申领者调用,也就是说,如果 claimerFor[claim.earner]
为 address(0)
,则只有赚取者可以申领,否则只有 claimerFor[claim.earner]
可以申领奖励。processClaims()
将迭代多个 claims
,并为每个申领调用 _processClaim()
。EarnerTreeMerkleLeaf
作为树中的内部叶子。每个赚取者叶子都有自己的子树,其中 TokenTreeMerkleLeaf
作为子树中的叶子。为了证明针对指定的 rootIndex
(指定正在使用的 distributionRoot)的申领,该申领将首先验证赚取者叶子在树中是否包含在 _distributionRoots[rootIndex].root
中。然后,对于每个 token,它将验证 token 叶子在赚取者的子树中是否包含在赚取者的 earnerTokenRoot
中。RewardsClaimed
事件。cumulativeEarnings
和 cumulativeClaimed
之间的差额。然后,此差额将转移到 recipient
地址。CALCULATION_INTERVAL_SECONDS
将从 1 周更新为 1 天,以反映 sidecar 中发生的每日奖励计算。这将使 AVS 能够提交 startTimestamp
和 duration
是 1 天而不是 1 周的倍数的奖励。
globalOperatorCommissionBips
重命名为 defaultOperatorSplitBips
这是接口中的一个重大更改。globalOperatorCommissionBips
公共存储变量将在 RewardsCoordinator
合约中的所有实例中重命名为 defaultOperatorSplitBips
。
EigenLayer 中间件应具有强制性版本,作为此 ELIP 的一部分,以支持基于绩效的奖励。AVS 必须升级其各自的 AVSServiceManager
合约,以继承新的 ServiceManagerBase
实现,以便能够提交基于绩效的奖励。
可以在下面找到 ServiceManagerBase
中 Operator 定向奖励的接口:
/**
* @notice 创建一个新的 Operator 定向奖励提交,以在 Operator 和委托给注册到此 `avs` 的 Operator 的 Staker 集之间进行划分。
* @param operatorDirectedRewardsSubmissions 要创建的 Operator 定向奖励提交
*/
function createOperatorDirectedAVSRewardsSubmission(IRewardsCoordinator.OperatorDirectedRewardsSubmission[] calldata operatorDirectedRewardsSubmissions) external;
/**
* @notice 将调用转发到 Eigenlayer 的 RewardsCoordinator 合约,以设置可以代表此合约调用 `processClaim` 的实体的地址。
* @param claimer 可以代表赚取者调用 `processClaim` 的实体的地址
*/
function setClaimerFor(address claimer) external;
createOperatorDirectedAVSRewardsSubmission()
必须包含以上字段;没有一个是可选的。rewardsInitiator
才能调用它。否则抛出错误。operatorDirectedRewardsSubmissions
:
AVSServiceManager
。RewardsCoordinator
用于该 token 中的奖励总额。RewardsCoordinator
合约中调用 createOperatorDirectedAVSRewardsSubmission
。operatorDirectedRewardsSubmission
对象必须遵守 RewardsCoordinator.createOperatorDirectedAVSRewardsSubmission
中的验证createOperatorDirectedAVSRewardsSubmission
之前,AVSServiceManager
合约需要 operatorDirectedRewardsSubmissions
中所有 operatorRewards
总和的 token 批准。EigenLayer Sidecar 是一个开源的、无需许可的、经过验证的索引器,它使任何人(AVS、Operator 等)都可以实时访问 EigenLayer 的协议奖励和 EigenLayer 状态。作为此 ELIP 的一部分,EigenLayer Sidecar 必须强制发布,以增强基于性能的奖励。这是 Rewards v2 流程的关键部分。
将引入以下高级功能:
OperatorDirectedAVSRewardsSubmissionCreated
、OperatorAVSSplitBipsSet
、OperatorPISplitBipsSet
。Rewards v2 版本将包括对 3 个新支持的事件的状态模型:OperatorDirectedAVSRewardsSubmissionCreated
、OperatorAVSSplitBipsSet
和 OperatorPISplitBipsSet
。
// `OperatorDirectedAVSRewardsSubmissionCreated` 事件的 Eigen State Schema
type OperatorDirectedRewardSubmission struct {
Avs string
RewardHash string
Token string
Operator string
OperatorIndex uint64
Amount string
Strategy string
StrategyIndex uint64
Multiplier string
StartTimestamp *time.Time
EndTimestamp *time.Time
Duration uint64
Description string
BlockNumber uint64
TransactionHash string
LogIndex uint64
}
// `OperatorAVSSplitBipsSet` 事件的 Eigen State Schema
type OperatorAVSSplit struct {
Operator string
Avs string
ActivatedAt *time.Time
OldOperatorAVSSplitBips uint64
NewOperatorAVSSplitBips uint64
BlockNumber uint64
TransactionHash string
LogIndex uint64
}
// `OperatorPISplitBipsSet` 事件的 Eigen State Schema
type OperatorPISplit struct {
Operator string
ActivatedAt *time.Time
OldOperatorAVSSplitBips uint64
NewOperatorAVSSplitBips uint64
BlockNumber uint64
TransactionHash string
LogIndex uint64
}
每个新事件都将被 sidecar 摄取、处理并根据上述 schema 存储在 sidecar 的内部数据库中的各自的表中。
Rewards v2 版本将包括一个新的 Operator 指导的奖励计算,该计算考虑了每个 avs 的 Operator 拆分。
Operator 指导的奖励计算将遵循此处指定的现有奖励计算实施。
此外还有以下内容:
operator_avs_split
表中存在特定 operator
的已激活的 OperatorAVSSplit
行,则使用该 split
进行奖励计算。Rewards MVP 计算将被更新,以包括作为 Rewards v2 一部分发布的每个 avs 的 Operator 拆分。
operator_avs_split
表中存在特定 operator
的已激活的 OperatorAVSSplit
行,则使用该 split
进行奖励计算。Programmatic Incentives 计算将被更新,以包括作为 Rewards v2 一部分发布的每个 avs 的 Operator 拆分。
operator_pi_split
表中存在特定 operator
的已激活的 OperatorPISplit
行,则使用该 split
进行奖励计算。关键安全考虑因素包括:
无需许可的可验证性:
防止奖励分配树膨胀:
已对 Rewards v2 进行了 2 次审计:
Rewards v2 的预期影响包括:
优点:
缺点:
此 ELIP 的实施将遵循以下关键步骤:
RewardsCoordinator
透明代理以指向一个新的实现合约,该合约引入了此处指定的逻辑。ServiceManagerBase
发布一个新版本,其中引入了此处指定的逻辑。 AVS 必须升级其各自的 AVSServiceManager
合约以继承新的 ServiceManagerBase
实现,以便能够提交基于性能的奖励。此过程将首先在 Eigen 测试网上开始,然后在 AVS 进行测试和集成后在主网上进行,以确保成功。 在主网之后,将通过索引链上奖励的事件来跟踪 Rewards v2 的采用情况。 这可以帮助确定此 ELIP 的成功并跟踪对协议的改进。
Operator Working Group October 2024 AVS Working Group October 2024
- 原文链接: github.com/eigenfoundati...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!