分红协议是什么意思_红利指数选股规则「建议收藏」

分红协议是什么意思_红利指数选股规则「建议收藏」Profit合约:统一的分红管理方案概要由于aelf主链采用DPoS共识机制,通过持有代币或者锁仓来获得权益是aelf治理模型中重要组成部分

分红协议是什么意思_红利指数选股规则「建议收藏」"

Profit合约:统一的分红管理方案
概要
由于aelf主链采用DPoS共识机制,通过持有代币或者锁仓来获得权益是aelf治理模型中重要组成部分。这就产生了一个需求:实现一个能够统一管理分红的标准流程,并将其作为一个基础的智能合约。这个合约在创世区块中即部署于链上,其应用包括但不限于:生产节点在某一届任期结束时根据其区块生产数量(以此作为权重)获得相应奖励,选民通过节点竞选投票所质押ELF来分享相应的奖励,DApp合约允许用户通过抵押Token来分享合约盈利。

分红方案即代币分配策略:任何地址都可以成为分红方案(profit scheme)的管理者(manager)。每个管理者(manager)都可以为该分红方案添加受益人(beneficiary),并为每个受益人设定股份(shares)。之后,当分红项目创建者对其项目受益人发放(distribute)分红时,将按其对应的股份进行代币分配。每次分红结束后,分红方案的账期(period)即加一,根据具体分红数额会在该账期对应的虚拟地址(virtual address)上增加余额,持有股份的账户可以从中获得相应分红。分红的受益人不仅可以是账户地址,也可以是另一个分红方案,子分红方案所获分红可直接打进其总账(general ledger)。分红方案之间可以进行级联。

进一步阐述几个概念:

分红方案(profit scheme):通过分红合约创建出来的代币分配中心。

分红方案管理者(manager):管理分红方案的受益人及其相应股份。

分红受益人(beneficiary):aelf区块链上用来接收分红代币的账户地址。要注意的是,受益人的分红需要通过发送交易来获取(需填入对应分红方案的id,交易由自己或他人发送皆可)。

分红方案虚拟地址(virtual address):每个分红方案都会通过其唯一标识(scheme id)映射一个虚拟地址,这个地址仅用来释放分红,没有对应的公私钥对(公私钥对碰撞出来的概率可以忽略不计)。

子分红方案(sub profit item):这是一个相对概念,每个分红方案都可能成为子分红方案。子分红方案可持有其父分红方案股份,这样父分红方案在释放分红时,子分红方案的虚拟地址会获得相应代币。

获取分红(claim profits):作为一个普通用户,需要自行发送交易来获取自己应得的分红,这是为了避免注册的接收地址过多,释放分红的交易执行超时。

股份(shares):股份是每个分红受益人能够获取相应分红比例的证明,即某受益人分红数量 = 总分红 * 该受益人持有股份 / 总股份。

发放分红(distribute profits):将分红方案虚拟地址上的余额通过Bancor合约转化为ELF,并Transfer给分红接收地址的过程。

账期(period):账期时长由分红方案的管理者自行控制,发放分红后账期自行增一。

国库(Treasury):可能是aelf区块链中额度最大的分红方案,其主要管理者为Treasury合约,另有两个子分红方案相应的管理者为Election合约。其分红额度来源于区块生产奖励,当前每生产一个区块,分红额度即增加0.125个ELF,在本届任期结束的时候统一打入Treasury scheme总账,随后Treasury合约和Election合约负责维护七个分红方案。
方法解读
创建分红方案
顾名思义,该接口用来创建分红方案。接口如下:
rpc CreateScheme (CreateSchemeInput) returns (aelf.Hash) {

}

message CreateSchemeInput {

sint64 profit_receiving_due_period_count = 1;
bool is_release_all_balance_every_time_by_default = 2;
sint32 delay_distribute_period_count = 3;
aelf.Address manager = 4;
bool can_remove_beneficiary_directly = 5;
}

message Scheme {

aelf.Address virtual_address = 1;
sint64 total_shares = 2;
map<string, sint64> undistributed_profits = 3;// token symbol -> amount
sint64 current_period = 4;
repeated SchemeBeneficiaryShare sub_schemes = 5;
bool can_remove_beneficiary_directly = 6;
sint64 profit_receiving_due_period_count = 7;
bool is_release_all_balance_every_time_by_default = 8;
aelf.Hash scheme_id = 9;
sint32 delay_distribute_period_count = 10;
map<sint64, sint64> cached_delay_total_shares = 11;// period -> total shares, max elements count should be delay_distribute_period_count
aelf.Address manager = 12;
}

message SchemeBeneficiaryShare {

aelf.Hash scheme_id = 1;
sint64 shares = 2;
}
一个分红方案,包含以下属性:
一个唯一的虚拟地址,作为该分红方案的总账地址;
总股份;
尚未发放余额(可能移除);
当前账期期数;
子分红方案信息;
是否允许直接移除分红受益人(无视其可领取期数);
分红保留期数(过期即无法领取);
默认发放总账上某token对应的全部额度;
分红方案唯一标识;
延迟发放期数;
延迟发放分红所需缓存上的被推迟发放总股份;
管理者。
///
/// Create a Scheme of profit distribution.
/// At the first time, the scheme’s id is unknown,it may create by transaction id and createdSchemeIds;
///
///
///
public override Hash CreateScheme(CreateSchemeInput input)
{

ValidateContractState(State.TokenContract, SmartContractConstants.TokenContractSystemName);

if (input.ProfitReceivingDuePeriodCount == 0)
{
    // 为了避免分红合约State信息过多,设置一个过期时间。
    input.ProfitReceivingDuePeriodCount = ProfitContractConstants.DefaultProfitReceivingDuePeriodCount;
}

var manager = input.Manager ?? Context.Sender;
var schemeId = Context.TransactionId;
// Why? Because one transaction may create many profit items via inline transactions.
var createdSchemeIds = State.ManagingSchemeIds[manager]?.SchemeIds;
if (createdSchemeIds != null && createdSchemeIds.Contains(schemeId))
{
    // So we choose this way to avoid profit id conflicts in aforementioned situation.
    schemeId = Hash.FromTwoHashes(schemeId, createdSchemeIds.Last());
}

var scheme = GetNewScheme(input, schemeId, manager);
State.SchemeInfos[schemeId] = scheme;

var schemeIds = State.ManagingSchemeIds[scheme.Manager];
if (schemeIds == null)
{
    schemeIds = new CreatedSchemeIds
    {
        SchemeIds = {schemeId}
    };
}
else
{
    schemeIds.SchemeIds.Add(schemeId);
}

State.ManagingSchemeIds[scheme.Manager] = schemeIds;

Context.LogDebug(() => $"Created scheme {State.SchemeInfos[schemeId]}");

Context.Fire(new SchemeCreated
{
    SchemeId = scheme.SchemeId,
    Manager = scheme.Manager,
    IsReleaseAllBalanceEveryTimeByDefault = scheme.IsReleaseAllBalanceEveryTimeByDefault,
    ProfitReceivingDuePeriodCount = scheme.ProfitReceivingDuePeriodCount,
    VirtualAddress = scheme.VirtualAddress
});
return schemeId;

}
子分红方案管理
用以添加和删除子分红方案。
rpc AddSubScheme (AddSubSchemeInput) returns (google.protobuf.Empty) {

}
rpc RemoveSubScheme (RemoveSubSchemeInput) returns (google.protobuf.Empty) {

}

message AddSubSchemeInput {

aelf.Hash scheme_id = 1;
aelf.Hash sub_scheme_id = 2;
sint64 sub_scheme_shares = 3;
}

message RemoveSubSchemeInput {

aelf.Hash scheme_id = 1;
aelf.Hash sub_scheme_id = 2;
}
其中,添加子分红方案需要分别填入两个发生级联关系的分红方案的id,然后需输入子分红项目所占股份。而移除级联关系只需要分别输入两个分红方案的id即可。
///
/// Add a child to a existed scheme.
///
/// AddSubSchemeInput
///
public override Empty AddSubScheme(AddSubSchemeInput input)
{

Assert(input.SchemeId != input.SubSchemeId, “Two schemes cannot be same.”);
Assert(input.SubSchemeShares > 0, “Shares of sub scheme should greater than 0.”);

var scheme = State.SchemeInfos[input.SchemeId];
Assert(scheme != null, "Scheme not found.");
Assert(Context.Sender == scheme.Manager, "Only manager can add sub-scheme.");

var subSchemeId = input.SubSchemeId;
var subScheme = State.SchemeInfos[subSchemeId];
Assert(subScheme != null, "Sub scheme not found.");

var subItemVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeId);
// Add profit details and total shares of the father scheme.
AddBeneficiary(new AddBeneficiaryInput
{
    SchemeId = input.SchemeId,
    BeneficiaryShare = new BeneficiaryShare
    {
        Beneficiary = subItemVirtualAddress,
        Shares = input.SubSchemeShares
    },
    EndPeriod = long.MaxValue
});

// Add a sub profit item.
scheme.SubSchemes.Add(new SchemeBeneficiaryShare
{
    SchemeId = input.SubSchemeId,
    Shares = input.SubSchemeShares
});
State.SchemeInfos[input.SchemeId] = scheme;

return new Empty();

}

public override Empty RemoveSubScheme(RemoveSubSchemeInput input)
{

Assert(input.SchemeId != input.SubSchemeId, “Two schemes cannot be same.”);

var scheme = State.SchemeInfos[input.SchemeId];
Assert(scheme != null, "Scheme not found.");
if (scheme == null) return new Empty();

Assert(Context.Sender == scheme.Manager, "Only manager can remove sub-scheme.");

var subSchemeId = input.SubSchemeId;
var subScheme = State.SchemeInfos[subSchemeId];
Assert(subScheme != null, "Sub scheme not found.");
if (subScheme == null) return new Empty();

var subSchemeVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeId);
// Remove profit details
State.ProfitDetailsMap[input.SchemeId][subSchemeVirtualAddress] = new ProfitDetails();

var shares = scheme.SubSchemes.Single(d => d.SchemeId == input.SubSchemeId);
scheme.SubSchemes.Remove(shares);
scheme.TotalShares = scheme.TotalShares.Sub(shares.Shares);
State.SchemeInfos[input.SchemeId] = scheme;

return new Empty();

}
受益人管理
用以添加和删除分红受益人,为方便起见提供了批量管理接口。
rpc AddBeneficiary (AddBeneficiaryInput) returns (google.protobuf.Empty) {

}
rpc RemoveBeneficiary (RemoveBeneficiaryInput) returns (google.protobuf.Empty) {

}
rpc AddBeneficiaries (AddBeneficiariesInput) returns (google.protobuf.Empty) {

}
rpc RemoveBeneficiaries (RemoveBeneficiariesInput) returns (google.protobuf.Empty) {

}

message AddBeneficiaryInput {

aelf.Hash scheme_id = 1;
BeneficiaryShare beneficiary_share = 2;
sint64 end_period = 3;
}

message RemoveBeneficiaryInput {

aelf.Address beneficiary = 1;
aelf.Hash scheme_id = 2;
}

message AddBeneficiariesInput {

aelf.Hash scheme_id = 1;
repeated BeneficiaryShare beneficiary_shares = 2;
sint64 end_period = 4;
}

message RemoveBeneficiariesInput {

repeated aelf.Address beneficiaries = 1;
aelf.Hash scheme_id = 2;
}

message BeneficiaryShare {

aelf.Address beneficiary = 1;
sint64 shares = 2;
}
在添加分红受益人时,除了需要指定分红方案id、分红受益人地址和股份,还可以指定该受益人能够接收分红的最后账期期数,默认是一经添加,即能永久收到分红,直到分红方案管理者调用RemoveBeneficiary方法将其股份移除(如果该分红方案的can_remove_beneficiary_directly属性值为true,可以直接移除全部股份)。
public override Empty AddBeneficiary(AddBeneficiaryInput input)
{

AssertValidInput(input);
if (input.BeneficiaryShare == null) return new Empty();

if (input.EndPeriod == 0)
{
    // Which means this profit Beneficiary will never expired unless removed.
    input.EndPeriod = long.MaxValue;
}

var schemeId = input.SchemeId;
var scheme = State.SchemeInfos[schemeId];

Assert(scheme != null, "Scheme not found.");
if (scheme == null) return new Empty();

Assert(
    Context.Sender == scheme.Manager || Context.Sender ==
    Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName),
    "Only manager can add beneficiary.");

Context.LogDebug(() =>
    $"{input.SchemeId}.\n End Period: {input.EndPeriod}, Current Period: {scheme.CurrentPeriod}");

Assert(input.EndPeriod >= scheme.CurrentPeriod, "Invalid end period.");

scheme.TotalShares = scheme.TotalShares.Add(input.BeneficiaryShare.Shares);

State.SchemeInfos[schemeId] = scheme;

var profitDetail = new ProfitDetail
{
    StartPeriod = scheme.CurrentPeriod.Add(scheme.DelayDistributePeriodCount),
    EndPeriod = input.EndPeriod,
    Shares = input.BeneficiaryShare.Shares,
};

var currentProfitDetails = State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary];
if (currentProfitDetails == null)
{
    currentProfitDetails = new ProfitDetails
    {
        Details = {profitDetail}
    };
}
else
{
    currentProfitDetails.Details.Add(profitDetail);
}

// Remove details too old.
foreach (var detail in currentProfitDetails.Details.Where(
    d => d.EndPeriod != long.MaxValue && d.LastProfitPeriod >= d.EndPeriod &&
         d.EndPeriod.Add(scheme.ProfitReceivingDuePeriodCount) < scheme.CurrentPeriod))
{
    currentProfitDetails.Details.Remove(detail);
}

State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary] = currentProfitDetails;

Context.LogDebug(() =>
    $"Added {input.BeneficiaryShare.Shares} weights to scheme {input.SchemeId.ToHex()}: {profitDetail}");

return new Empty();

}

public override Empty RemoveBeneficiary(RemoveBeneficiaryInput input)
{

Assert(input.SchemeId != null, “Invalid scheme id.”);
Assert(input.Beneficiary != null, “Invalid Beneficiary address.”);

var scheme = State.SchemeInfos[input.SchemeId];

Assert(scheme != null, "Scheme not found.");

var currentDetail = State.ProfitDetailsMap[input.SchemeId][input.Beneficiary];

if (scheme == null || currentDetail == null) return new Empty();

Assert(Context.Sender == scheme.Manager || Context.Sender ==
       Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName),
    "Only manager can remove beneficiary.");

var expiryDetails = 

今天的文章分红协议是什么意思_红利指数选股规则「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/89143.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注