From b7fa1bfe33b264278278bdb682fb6676687ca05b Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Mon, 2 Dec 2024 21:39:55 +0800
Subject: [PATCH 1/9] add normal seed renew
---
.../Forest.Contracts.SymbolRegistrar.csproj | 3 +
.../SymbolRegistrarContractConstants.cs | 2 +
.../SymbolRegistrarContract_Action.cs | 52 ++++++++++++++
.../SymbolRegistrarContract_Helper.cs | 25 +++++++
protobuf/symbol_registrar_contract.proto | 27 ++++++-
protobuf/token_contract_impl.proto | 70 ++++++++++++-------
6 files changed, 151 insertions(+), 28 deletions(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj b/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj
index fe15d2b9..76490d11 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj
+++ b/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj
@@ -40,6 +40,9 @@
Protobuf\Proto\reference\token_contract.proto
+
+ Protobuf\Proto\token_contract_impl.proto
+
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractConstants.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractConstants.cs
index ad43c930..82a5e115 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractConstants.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractConstants.cs
@@ -16,6 +16,8 @@ public class SymbolRegistrarContractConstants
public const int MaxAddSpecialSeedCount = 500;
public const int MaxSymbolLength = 30;
public const string SeedPrefix = "SEED-";
+ public const string SeedPrefixPart = "SEED";
+
public const int MaxCycleCount = 30;
public const string CollectionSymbolSuffix = "0";
public const string SeedOwnedSymbolExternalInfoKey = "__seed_owned_symbol";
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
index a83450d3..f9930d2e 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
@@ -124,6 +124,11 @@ private void DoCreateSeed(Address to, string symbol, long expireTime = 0)
ImageUrl = seedInfo.ImageUrl
});
}
+
+ private void DoRenewSeed(string seedSymbol, long expireTime = 0)
+ {
+ //State.TokenContract
+ }
private bool CreateSeedToken(Address issuer, string symbol, long expireTime = 0)
{
@@ -213,5 +218,52 @@ private Hash GetProxyAccountHash()
State.ProxyAccountHash.Value = proxyAccount.ProxyAccountHash;
return proxyAccount.ProxyAccountHash;
}
+
+ public override Empty GeneralSeedRenew(GeneralSeedRenewInput input)
+ {
+ AssertContractInitialize();
+ AssertSeedSymbolPattern(input.SeedSymbol);
+ CheckSeedBalanceExisted(input.SeedSymbol);
+ var seedTokenInfo = GetTokenInfo(input.SeedSymbol);
+ Assert(seedTokenInfo.Symbol.Length > 1, "Seed Symbol not exists");
+ var seedOwnedSymbol = seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedOwnedSymbolExternalInfoKey];
+ var seedExpTime = long.Parse(seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedExpireTimeExternalInfoKey]);
+ Assert(!string.IsNullOrWhiteSpace(seedOwnedSymbol) && seedExpTime > Context.CurrentBlockTime.Seconds, "symbol seed not existed or expired");
+
+ var specialSeed = State.SpecialSeedMap[seedOwnedSymbol];
+ Assert(specialSeed == null, "Special seed " + input.SeedSymbol + " not support renew.");
+
+ var price = GetDealPrice(seedOwnedSymbol);
+ Assert(price != null, "Symbol price not exits");
+ Assert(price.Symbol == input.Price.Symbol && price.Amount == input.Price.Amount, "input symbol price not correct");
+
+ State.TokenContract.TransferFrom.Send(new TransferFromInput()
+ {
+ From = Context.Sender,
+ To = State.ReceivingAccount.Value,
+ Symbol = price.Symbol,
+ Amount = price.Amount,
+ });
+
+ var nextExpTime = seedExpTime + State.SeedExpirationConfig.Value;
+ DoRenewSeed(input.SeedSymbol, nextExpTime);
+
+ Context.Fire(new SeedRenewed()
+ {
+ Buyer = Context.Sender,
+ Symbol = seedOwnedSymbol,
+ SeedSymbol = input.SeedSymbol,
+ ExpTime = nextExpTime,
+ Price = new Price
+ {
+ Symbol = input.Price.Symbol,
+ Amount = input.Price.Amount
+ }
+ });
+
+ return new Empty();
+ }
}
+
+
}
\ No newline at end of file
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
index ca74340c..9c0e839e 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
@@ -55,6 +55,21 @@ private void AssertSymbolPattern(string symbol)
}
}
+ private void AssertSeedSymbolPattern(string symbol)
+ {
+ Assert(symbol.Length > 0 && symbol.Length <= SymbolRegistrarContractConstants.MaxSymbolLength,
+ "Invalid symbol length.");
+
+ var symbolPartition = symbol.Split(SymbolRegistrarContractConstants.NFTSymbolSeparator);
+ Assert(symbolPartition.Length == 2, "Invalid symbol.");
+ Assert(symbolPartition[0] == SymbolRegistrarContractConstants.SeedPrefixPart, "Invalid seed symbol prefix.");
+
+ foreach (var c in symbolPartition[1])
+ {
+ Assert(c >= 1 && c <= 9, "Invalid seed symbol suffix.");
+ }
+ }
+
private void AssertPriceListLength(PriceList priceList)
{
Assert(priceList?.Value?.Count == SymbolRegistrarContractConstants.MaxSymbolLength,
@@ -155,5 +170,15 @@ private void CheckSymbolExisted(string symbol)
var collectionSeed = State.SymbolSeedMap[collectionSymbol];
Assert(string.IsNullOrWhiteSpace(collectionSeed) || State.SeedInfoMap[collectionSeed].ExpireTime < Context.CurrentBlockTime.Seconds, "symbol seed existed");
}
+
+ private void CheckSeedBalanceExisted(string symbol)
+ {
+ var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput
+ {
+ Symbol = symbol,
+ Owner = Context.Sender
+ });
+ Assert(balance.Balance == 1, $"you don't have enough {symbol}");
+ }
}
}
\ No newline at end of file
diff --git a/protobuf/symbol_registrar_contract.proto b/protobuf/symbol_registrar_contract.proto
index 2b711d6e..c63f614a 100644
--- a/protobuf/symbol_registrar_contract.proto
+++ b/protobuf/symbol_registrar_contract.proto
@@ -32,6 +32,12 @@ service SymbolRegistrarContract {
rpc Buy(BuyInput) returns (google.protobuf.Empty){
}
+
+ rpc GeneralSeedRenew(GeneralSeedRenewInput) returns (google.protobuf.Empty){
+ }
+
+ rpc SpecialSeedRenew(SpecialSeedRenewInput) returns (google.protobuf.Empty){
+ }
// for Parliament contract
// when proposal has been approved special-seeds will be add
@@ -269,7 +275,6 @@ message SpecialSeed {
map external_info = 8;
}
-
message BuyInput{
// the symbol to buy
string symbol = 1;
@@ -277,6 +282,17 @@ message BuyInput{
aelf.Address issue_to = 2;
}
+message GeneralSeedRenewInput{
+ //seedSymbol
+ string seed_symbol = 1;
+ Price price = 2;
+}
+
+message SpecialSeedRenewInput{
+ string seed_symbol = 1;
+ Price price = 2;
+}
+
message ControllerList{
repeated aelf.Address controllers = 1;
}
@@ -354,6 +370,15 @@ message Bought {
Price price = 4;
}
+message SeedRenewed {
+ option (aelf.is_event) = true;
+ aelf.Address buyer = 1;
+ string symbol = 2;
+ string seed_symbol = 3;
+ int64 exp_time = 4;
+ Price price = 5;
+}
+
message SaleControllerAdded {
option (aelf.is_event) = true;
ControllerList addresses = 1;
diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto
index 5885914e..fbccc194 100644
--- a/protobuf/token_contract_impl.proto
+++ b/protobuf/token_contract_impl.proto
@@ -24,11 +24,11 @@ service TokenContractImpl {
option (aelf.base) = "acs1.proto";
option (aelf.base) = "acs2.proto";
option (aelf.base) = "token_contract.proto";
-
+
// Transfer resource tokens to designated contract address.
rpc AdvanceResourceToken (AdvanceResourceTokenInput) returns (google.protobuf.Empty) {
}
-
+
// Take token from contract address.
rpc TakeResourceTokenBack (TakeResourceTokenBackInput) returns (google.protobuf.Empty) {
}
@@ -36,15 +36,15 @@ service TokenContractImpl {
// Register the token contract address for cross chain.
rpc RegisterCrossChainTokenContractAddress (RegisterCrossChainTokenContractAddressInput) returns (google.protobuf.Empty) {
}
-
+
// Set the receiver address of the side chain transaction fee.
rpc SetFeeReceiver (aelf.Address) returns (google.protobuf.Empty) {
}
-
+
// Validates if the token exist.
rpc ValidateTokenInfoExists(ValidateTokenInfoExistsInput) returns (google.protobuf.Empty){
}
-
+
// Update the rental unit price of the side chain.
rpc UpdateRental (UpdateRentalInput) returns (google.protobuf.Empty) {
}
@@ -56,23 +56,23 @@ service TokenContractImpl {
// Transfer Token to the specified contract.
rpc TransferToContract (TransferToContractInput) returns (google.protobuf.Empty) {
}
-
+
// Change the governance organization of side chain rental.
rpc ChangeSideChainRentalController (AuthorityInfo) returns (google.protobuf.Empty) {
}
-
+
// Change the governance organization for tokens to pay transaction fees.
rpc ChangeSymbolsToPayTXSizeFeeController(AuthorityInfo) returns (google.protobuf.Empty){
}
-
+
// Change the governance organization for cross-chain token contract address registration.
rpc ChangeCrossChainTokenContractRegistrationController (AuthorityInfo) returns (google.protobuf.Empty) {
}
-
+
// Change the governance organization of the coefficient of the user transaction fee calculation formula.
rpc ChangeUserFeeController (AuthorityInfo) returns (google.protobuf.Empty) {
}
-
+
// Change the governance organization of the coefficient of the developer's transaction resource fee calculation formula.
rpc ChangeDeveloperController (AuthorityInfo) returns (google.protobuf.Empty) {
}
@@ -84,18 +84,18 @@ service TokenContractImpl {
}
rpc SetMaxBatchApproveCount (google.protobuf.Int32Value) returns (google.protobuf.Empty) {
-
+
}
-
+
// Delegatee sets the delegation and related information of the delegator based on a transaction.
rpc SetTransactionFeeDelegateInfos (SetTransactionFeeDelegateInfosInput) returns (google.protobuf.Empty){
}
-
+
// Delegatee remove delegator info based on a transaction.
rpc RemoveTransactionFeeDelegatorInfos (RemoveTransactionFeeDelegatorInfosInput) returns (google.protobuf.Empty){
}
-
+
// Delegator remove delegatee info based on a transaction.
rpc RemoveTransactionFeeDelegateeInfos (RemoveTransactionFeeDelegateeInfosInput) returns (google.protobuf.Empty){
}
@@ -104,48 +104,48 @@ service TokenContractImpl {
rpc GetFeeReceiver (google.protobuf.Empty) returns (aelf.Address){
option (aelf.is_view) = true;
}
-
+
// Query the amount of resources usage currently.
rpc GetResourceUsage (google.protobuf.Empty) returns (ResourceUsage) {
option (aelf.is_view) = true;
}
-
+
// Query the governance organization for tokens to pay transaction fees.
rpc GetSymbolsToPayTXSizeFeeController(google.protobuf.Empty) returns (AuthorityInfo){
option (aelf.is_view) = true;
}
-
+
// Query the governance organization of the
rpc GetCrossChainTokenContractRegistrationController (google.protobuf.Empty) returns (AuthorityInfo) {
option (aelf.is_view) = true;
}
-
+
// Query the governance organization that calculates the formula coefficient
// for the transaction cost the user sends the contract.
rpc GetUserFeeController(google.protobuf.Empty) returns (UserFeeController){
option (aelf.is_view) = true;
}
-
+
// Query the governing organization of the formula coefficients for calculating developer contract transaction fee.
rpc GetDeveloperFeeController (google.protobuf.Empty) returns (DeveloperFeeController) {
option (aelf.is_view) = true;
}
-
+
// Query the organization that governs the side chain rental fee.
rpc GetSideChainRentalControllerCreateInfo (google.protobuf.Empty) returns (AuthorityInfo) {
option (aelf.is_view) = true;
}
-
+
// Compute the virtual address for locking.
rpc GetVirtualAddressForLocking (GetVirtualAddressForLockingInput) returns (aelf.Address) {
option (aelf.is_view) = true;
}
-
+
// Query how much resource tokens should be paid currently.
rpc GetOwningRental (google.protobuf.Empty) returns (OwningRental) {
option (aelf.is_view) = true;
}
-
+
// Query the unit price of the side chain resource cost, resource cost = unit price * quantity,
// the quantity can be queried through GetResourceUsage.
rpc GetOwningRentalUnitValue (google.protobuf.Empty) returns (OwningRentalUnitValue) {
@@ -159,7 +159,7 @@ service TokenContractImpl {
rpc GetTransactionFeeFreeAllowancesConfig (google.protobuf.Empty) returns (GetTransactionFeeFreeAllowancesConfigOutput) {
option (aelf.is_view) = true;
}
-
+
// Get delegatee info list according to the delegator and transaction.
rpc GetTransactionFeeDelegateeList (GetTransactionFeeDelegateeListInput) returns (GetTransactionFeeDelegateeListOutput) {
option (aelf.is_view) = true;
@@ -168,13 +168,13 @@ service TokenContractImpl {
rpc GetTransactionFeeDelegateInfo(GetTransactionFeeDelegateInfoInput) returns (token.TransactionFeeDelegations){
option (aelf.is_view) = true;
}
-
+
rpc ModifyTokenIssuerAndOwner(ModifyTokenIssuerAndOwnerInput) returns (google.protobuf.Empty) {
}
-
+
rpc SetTokenIssuerAndOwnerModificationEnabled(SetTokenIssuerAndOwnerModificationEnabledInput) returns (google.protobuf.Empty) {
}
-
+
rpc GetTokenIssuerAndOwnerModificationEnabled(google.protobuf.Empty) returns (google.protobuf.BoolValue) {
option (aelf.is_view) = true;
}
@@ -182,6 +182,9 @@ service TokenContractImpl {
rpc GetMaxBatchApproveCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) {
}
+
+ rpc ExtendSeedExpirationTime (ExtendSeedExpirationTimeInput) returns (google.protobuf.Empty) {
+ }
}
message AdvanceResourceTokenInput {
@@ -444,4 +447,17 @@ message ModifyTokenIssuerAndOwnerInput {
message SetTokenIssuerAndOwnerModificationEnabledInput{
bool enabled = 1;
+}
+
+message ExtendSeedExpirationTimeInput {
+ string symbol = 1;
+ int64 expiration_time = 2;
+}
+
+message SeedExpirationTimeUpdated {
+ option (aelf.is_event) = true;
+ int32 chain_id = 1;
+ string symbol = 2;
+ int64 old_expiration_time = 3;
+ int64 new_expiration_time = 4;
}
\ No newline at end of file
From f562d9f2b21371ae9fe42ab773d06fa22284d8b0 Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Mon, 2 Dec 2024 22:03:11 +0800
Subject: [PATCH 2/9] impl DoRenewSeed
---
.../SymbolRegistrarContractReferenceState.cs | 2 ++
.../SymbolRegistrarContract_Action.cs | 8 +++++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractReferenceState.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractReferenceState.cs
index 652caae8..b323b292 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractReferenceState.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractReferenceState.cs
@@ -20,5 +20,7 @@ internal AElf.Contracts.ProxyAccountContract.ProxyAccountContractContainer.Proxy
get;
set;
}
+
+ internal TokenContractImplContainer.TokenContractImplReferenceState TokenImplContract { get; set; }
}
}
\ No newline at end of file
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
index f9930d2e..4b11d437 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
@@ -127,7 +127,13 @@ private void DoCreateSeed(Address to, string symbol, long expireTime = 0)
private void DoRenewSeed(string seedSymbol, long expireTime = 0)
{
- //State.TokenContract
+
+ State.TokenImplContract.ExtendSeedExpirationTime.Send(
+ new ExtendSeedExpirationTimeInput
+ {
+ Symbol = seedSymbol,
+ ExpirationTime = expireTime
+ });
}
private bool CreateSeedToken(Address issuer, string symbol, long expireTime = 0)
From 88945086bd11359cb917a8e3edb3060fec979e4a Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Tue, 3 Dec 2024 14:21:58 +0800
Subject: [PATCH 3/9] add bid seed renew
---
.../SymbolRegistrarContractState.cs | 5 +
.../SymbolRegistrarContract_Action.cs | 114 +++++++++++++++++-
.../SymbolRegistrarContract_Admin.cs | 15 +++
protobuf/symbol_registrar_contract.proto | 33 ++++-
4 files changed, 160 insertions(+), 7 deletions(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractState.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractState.cs
index fb8e9c42..f4ce56dd 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractState.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContractState.cs
@@ -40,5 +40,10 @@ public partial class SymbolRegistrarContractState : ContractState
public SingletonState IssueChainList { get; set; }
public SingletonState SeedCollectionOwner { get; set; }
public SingletonState ProxyAccountHash { get; set; }
+
+ public SingletonState SeedRenewHashVerifyKey { get; set; }
+ //seedSymbol -> renewTime
+ public MappedState SeedRenewTimeMap { get; set; }
+
}
}
\ No newline at end of file
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
index 4b11d437..4ff9f0ce 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
@@ -225,7 +225,7 @@ private Hash GetProxyAccountHash()
return proxyAccount.ProxyAccountHash;
}
- public override Empty GeneralSeedRenew(GeneralSeedRenewInput input)
+ public override Empty RegularSeedRenew(RegularSeedRenewInput input)
{
AssertContractInitialize();
AssertSeedSymbolPattern(input.SeedSymbol);
@@ -256,19 +256,129 @@ public override Empty GeneralSeedRenew(GeneralSeedRenewInput input)
Context.Fire(new SeedRenewed()
{
+ ChainId = Context.ChainId,
Buyer = Context.Sender,
Symbol = seedOwnedSymbol,
SeedSymbol = input.SeedSymbol,
ExpTime = nextExpTime,
+ OriginalExpTime = seedExpTime,
Price = new Price
{
Symbol = input.Price.Symbol,
Amount = input.Price.Amount
- }
+ },
+ SeedType = SeedType.Regular,
+ RenewType = RenewType.Self
});
return new Empty();
}
+
+ public override Empty SpecialSeedRenew(SpecialSeedRenewInput input)
+ {
+ AssertContractInitialize();
+ AssertSeedSymbolPattern(input.SeedSymbol);
+ CheckSeedBalanceExisted(input.SeedSymbol);
+ Assert(Context.Sender == input.Buyer, "param owner not sender");
+ var seedTokenInfo = GetTokenInfo(input.SeedSymbol);
+ Assert(seedTokenInfo.Symbol.Length > 1, "Seed Symbol not exists");
+ var seedOwnedSymbol = seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedOwnedSymbolExternalInfoKey];
+ var seedExpTime = long.Parse(seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedExpireTimeExternalInfoKey]);
+ Assert(!string.IsNullOrWhiteSpace(seedOwnedSymbol) && seedExpTime > Context.CurrentBlockTime.Seconds, "symbol seed not existed or expired");
+
+ var specialSeed = State.SpecialSeedMap[seedOwnedSymbol];
+ Assert(specialSeed != null, "Not Special seed " + input.SeedSymbol + " not support renew.");
+ var requestStr = string.Concat(input.Buyer.ToBase58(), input.SeedSymbol);
+ requestStr = string.Concat(requestStr, input.Price.Symbol, input.Price.Amount, input.OpTime);
+ CheckSeedRenewRequestHash(requestStr, input.RequestHash);
+ var lastAddTime = State.SeedRenewTimeMap[input.SeedSymbol];
+ Assert(input.OpTime > lastAddTime, "Invalid param OpTime");
+ State.SeedRenewTimeMap[input.SeedSymbol] = input.OpTime;
+
+ var price = input.Price;
+ Assert(price != null, "Symbol price not exits");
+ var priceTokenInfo = GetTokenInfo(price.Symbol);
+ Assert(priceTokenInfo != null, "input price symbol not correct");
+ Assert(price.Amount > 0, "input price amount not correct");
+
+ State.TokenContract.TransferFrom.Send(new TransferFromInput()
+ {
+ From = Context.Sender,
+ To = State.ReceivingAccount.Value,
+ Symbol = price.Symbol,
+ Amount = price.Amount,
+ });
+
+ var nextExpTime = seedExpTime + State.SeedExpirationConfig.Value;
+ DoRenewSeed(input.SeedSymbol, nextExpTime);
+
+ Context.Fire(new SeedRenewed()
+ {
+ ChainId = Context.ChainId,
+ Buyer = Context.Sender,
+ Symbol = seedOwnedSymbol,
+ SeedSymbol = input.SeedSymbol,
+ ExpTime = nextExpTime,
+ OriginalExpTime = seedExpTime,
+ Price = new Price
+ {
+ Symbol = input.Price.Symbol,
+ Amount = input.Price.Amount
+ },
+ SeedType = SeedType.Unique,
+ RenewType = RenewType.Self
+ });
+
+ return new Empty();
+ }
+
+
+ public override Empty BidFinishSeedRenew(BidFinishSeedRenewInput input)
+ {
+ AssertContractInitialize();
+ AssertSeedSymbolPattern(input.SeedSymbol);
+ CheckSeedBalanceExisted(input.SeedSymbol);
+ var seedTokenInfo = GetTokenInfo(input.SeedSymbol);
+ Assert(seedTokenInfo.Symbol.Length > 1, "Seed Symbol not exists");
+ var seedOwnedSymbol = seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedOwnedSymbolExternalInfoKey];
+ var seedExpTime = long.Parse(seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedExpireTimeExternalInfoKey]);
+ Assert(!string.IsNullOrWhiteSpace(seedOwnedSymbol) && seedExpTime > Context.CurrentBlockTime.Seconds, "symbol seed not existed or expired");
+ Assert(input.BidFinishTime > seedExpTime && input.BidFinishTime < Context.CurrentBlockTime.Seconds, "bid finish time not correct");
+
+ var specialSeed = State.SpecialSeedMap[seedOwnedSymbol];
+ Assert(specialSeed != null, "Not Special seed " + input.SeedSymbol + " not support renew.");
+ var requestStr = string.Concat(input.SeedSymbol, input.BidFinishTime, input.OpTime);
+ CheckSeedRenewRequestHash(requestStr, input.RequestHash);
+ var lastAddTime = State.SeedRenewTimeMap[input.SeedSymbol];
+ Assert(input.OpTime > lastAddTime, "Invalid param OpTime");
+ State.SeedRenewTimeMap[input.SeedSymbol] = input.OpTime;
+
+ var nextExpTime = input.BidFinishTime + State.SeedExpirationConfig.Value;
+ DoRenewSeed(input.SeedSymbol, nextExpTime);
+
+ Context.Fire(new SeedRenewed()
+ {
+ ChainId = Context.ChainId,
+ Buyer = Context.Sender,
+ Symbol = seedOwnedSymbol,
+ SeedSymbol = input.SeedSymbol,
+ ExpTime = nextExpTime,
+ OriginalExpTime = seedExpTime,
+ SeedType = SeedType.Unique,
+ RenewType = RenewType.Bid
+ });
+
+ return new Empty();
+ }
+
+ private void CheckSeedRenewRequestHash(string request, string hash)
+ {
+ var key = State.SeedRenewHashVerifyKey.Value;
+ Assert(!string.IsNullOrEmpty(key), "Need SetTreePointsHashVerifyKey");
+ var requestHash = HashHelper.ComputeFrom(string.Concat(request, key));
+ Assert(hash.Equals(requestHash.ToHex()), "Unverified requests");
+ }
+
}
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Admin.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Admin.cs
index 380fe285..1b11fd0c 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Admin.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Admin.cs
@@ -399,5 +399,20 @@ public override Empty RemoveIssueChain(IssueChainList input)
return new Empty();
}
+
+ public override Empty SetSeedRenewHashVerifyKey(StringValue input)
+ {
+ AssertInitialized();
+ Assert(input != null && !string.IsNullOrEmpty(input.Value), "Invalid param key");
+ var key = State.SeedRenewHashVerifyKey.Value;
+ if (string.IsNullOrEmpty(key))
+ {
+ State.SeedRenewHashVerifyKey.Value = input.Value;
+ return new Empty();
+ }
+ AssertAdmin();
+ State.SeedRenewHashVerifyKey.Value = input.Value;
+ return new Empty();
+ }
}
}
\ No newline at end of file
diff --git a/protobuf/symbol_registrar_contract.proto b/protobuf/symbol_registrar_contract.proto
index c63f614a..25aee1f7 100644
--- a/protobuf/symbol_registrar_contract.proto
+++ b/protobuf/symbol_registrar_contract.proto
@@ -33,12 +33,15 @@ service SymbolRegistrarContract {
rpc Buy(BuyInput) returns (google.protobuf.Empty){
}
- rpc GeneralSeedRenew(GeneralSeedRenewInput) returns (google.protobuf.Empty){
+ rpc RegularSeedRenew(RegularSeedRenewInput) returns (google.protobuf.Empty){
}
rpc SpecialSeedRenew(SpecialSeedRenewInput) returns (google.protobuf.Empty){
}
+ rpc BidFinishSeedRenew(BidFinishSeedRenewInput) returns (google.protobuf.Empty){
+ }
+
// for Parliament contract
// when proposal has been approved special-seeds will be add
rpc AddSpecialSeeds(SpecialSeedList) returns (google.protobuf.Empty) {
@@ -94,7 +97,8 @@ service SymbolRegistrarContract {
rpc RemoveIssueChain(IssueChainList) returns (google.protobuf.Empty) {
}
-
+ rpc SetSeedRenewHashVerifyKey(google.protobuf.StringValue)returns (google.protobuf.Empty){
+ }
// View
@@ -256,6 +260,11 @@ enum SeedType {
REGULAR = 4;
}
+enum RenewType {
+ SELF = 0;
+ BID = 1;
+}
+
message SpecialSeed {
// special seed
SeedType seed_type = 1;
@@ -281,16 +290,26 @@ message BuyInput{
// which address to issue
aelf.Address issue_to = 2;
}
-
-message GeneralSeedRenewInput{
+//REGULAR
+message RegularSeedRenewInput{
//seedSymbol
string seed_symbol = 1;
Price price = 2;
}
message SpecialSeedRenewInput{
+ aelf.Address buyer = 1;
+ string seed_symbol = 2;
+ Price price = 3;
+ int64 op_time = 4;
+ string request_hash = 5;
+}
+
+message BidFinishSeedRenewInput{
string seed_symbol = 1;
- Price price = 2;
+ int64 bid_finish_time = 2;
+ int64 op_time = 3;
+ string request_hash = 4;
}
message ControllerList{
@@ -377,6 +396,10 @@ message SeedRenewed {
string seed_symbol = 3;
int64 exp_time = 4;
Price price = 5;
+ int64 original_exp_time =6;
+ SeedType seed_type=7;
+ RenewType renew_type=8;
+ int32 chain_id = 9;
}
message SaleControllerAdded {
From f4ceb21793f878520aaf6bf54b0e2098427d7a5d Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Wed, 4 Dec 2024 14:08:10 +0800
Subject: [PATCH 4/9] fix seed check
---
.../SymbolRegistrarContract_Helper.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
index 9c0e839e..c5e5acd6 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
@@ -66,7 +66,7 @@ private void AssertSeedSymbolPattern(string symbol)
foreach (var c in symbolPartition[1])
{
- Assert(c >= 1 && c <= 9, "Invalid seed symbol suffix.");
+ Assert(c >= '1' && c <= '9', "Invalid seed symbol suffix.");
}
}
From 2d49b9363c5770f52a5d37bdc39fa52c34bad6c9 Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Wed, 4 Dec 2024 16:14:48 +0800
Subject: [PATCH 5/9] fix seed renew
---
.../Forest.Contracts.SymbolRegistrar.csproj | 10 +++++++++
.../SymbolRegistrarContract_Action.cs | 21 ++++++++++++++-----
.../SymbolRegistrarContractTests_Buy.cs | 16 +++++++++++++-
3 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj b/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj
index 76490d11..5d7acf82 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj
+++ b/contract/Forest.Contracts.SymbolRegistrar/Forest.Contracts.SymbolRegistrar.csproj
@@ -19,6 +19,12 @@
Protobuf\Proto\acs0.proto
+
+ Protobuf\Proto\reference\acs1.proto
+
+
+ Protobuf\Proto\reference\acs2.proto
+
Protobuf\Proto\acs3.proto
@@ -40,9 +46,13 @@
Protobuf\Proto\reference\token_contract.proto
+
Protobuf\Proto\token_contract_impl.proto
+
+ Protobuf\Proto\reference\transaction_fee.proto
+
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
index 4ff9f0ce..d9ddbcee 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
@@ -124,15 +124,26 @@ private void DoCreateSeed(Address to, string symbol, long expireTime = 0)
ImageUrl = seedInfo.ImageUrl
});
}
-
private void DoRenewSeed(string seedSymbol, long expireTime = 0)
{
+ if (State.TokenImplContract.Value == null)
+ {
+ State.TokenImplContract.Value = State.TokenContract.Value;
+ }
+
+ var renewInput = new ExtendSeedExpirationTimeInput
+ {
+ Symbol = seedSymbol,
+ ExpirationTime = expireTime
+ };
- State.TokenImplContract.ExtendSeedExpirationTime.Send(
- new ExtendSeedExpirationTimeInput
+ State.ProxyAccountContract.ForwardCall.Send(
+ new ForwardCallInput
{
- Symbol = seedSymbol,
- ExpirationTime = expireTime
+ ContractAddress = State.TokenContract.Value,
+ MethodName = nameof(State.TokenImplContract.ExtendSeedExpirationTime),
+ ProxyAccountHash = GetProxyAccountHash(),
+ Args = renewInput.ToByteString()
});
}
diff --git a/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs b/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs
index a3e42127..fc23011e 100644
--- a/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs
+++ b/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs
@@ -313,6 +313,20 @@ public async Task Buy_existsFT_fail()
res.ShouldNotBeNull();
res.Message.ShouldContain("Symbol exists");
}
-
+
+ [Fact]
+ public async Task SeedRenew_Test ()
+ {
+ await Buy_success();
+ await User1SymbolRegistrarContractStub.RegularSeedRenew.SendAsync(new RegularSeedRenewInput()
+ {
+ SeedSymbol = "SEED-1",
+ Price = new Price()
+ {
+ Symbol = "ELF",
+ Amount = 4700000000
+ }
+ });
+ }
}
}
\ No newline at end of file
From e4b7e9d5e69166ccfc43ac78640ea50c0edb1699 Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Wed, 4 Dec 2024 23:52:21 +0800
Subject: [PATCH 6/9] BidFinishSeedRenew no need check balance
---
.../SymbolRegistrarContract_Action.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
index d9ddbcee..4ab2cec8 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
@@ -348,13 +348,11 @@ public override Empty BidFinishSeedRenew(BidFinishSeedRenewInput input)
{
AssertContractInitialize();
AssertSeedSymbolPattern(input.SeedSymbol);
- CheckSeedBalanceExisted(input.SeedSymbol);
var seedTokenInfo = GetTokenInfo(input.SeedSymbol);
Assert(seedTokenInfo.Symbol.Length > 1, "Seed Symbol not exists");
var seedOwnedSymbol = seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedOwnedSymbolExternalInfoKey];
var seedExpTime = long.Parse(seedTokenInfo.ExternalInfo.Value[SymbolRegistrarContractConstants.SeedExpireTimeExternalInfoKey]);
Assert(!string.IsNullOrWhiteSpace(seedOwnedSymbol) && seedExpTime > Context.CurrentBlockTime.Seconds, "symbol seed not existed or expired");
- Assert(input.BidFinishTime > seedExpTime && input.BidFinishTime < Context.CurrentBlockTime.Seconds, "bid finish time not correct");
var specialSeed = State.SpecialSeedMap[seedOwnedSymbol];
Assert(specialSeed != null, "Not Special seed " + input.SeedSymbol + " not support renew.");
From 50ffd662520a3ae730c915dfdf5b49041f5306b2 Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Thu, 5 Dec 2024 10:54:42 +0800
Subject: [PATCH 7/9] add ut
---
.../SymbolRegistrarContract_Action.cs | 2 +-
.../SymbolRegistrarContractTests_Admin.cs | 13 +++++++++++++
.../SymbolRegistrarContractTests_Buy.cs | 16 ++++++++++++++++
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
index 4ab2cec8..f9daf2aa 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
@@ -383,7 +383,7 @@ public override Empty BidFinishSeedRenew(BidFinishSeedRenewInput input)
private void CheckSeedRenewRequestHash(string request, string hash)
{
var key = State.SeedRenewHashVerifyKey.Value;
- Assert(!string.IsNullOrEmpty(key), "Need SetTreePointsHashVerifyKey");
+ Assert(!string.IsNullOrEmpty(key), "Need Set SeedRenewHashVerifyKey");
var requestHash = HashHelper.ComputeFrom(string.Concat(request, key));
Assert(hash.Equals(requestHash.ToHex()), "Unverified requests");
}
diff --git a/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Admin.cs b/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Admin.cs
index 4215cf07..5c5419a2 100644
--- a/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Admin.cs
+++ b/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Admin.cs
@@ -515,5 +515,18 @@ public async Task IssueChainListTests()
}
+
+ [Fact]
+ public async Task SetSeedRenewHashVerifyKeyTests()
+ {
+ await InitializeContract();
+ var value = "1a2b3c";
+ await AdminSymbolRegistrarContractStub.SetSeedRenewHashVerifyKey.SendAsync(new StringValue()
+ {
+ Value = value
+ });
+ var result = AdminSymbolRegistrarContractStub.GetSeedRenewHashVerifyKey.CallAsync(new Empty());
+ result.Result.Value.ShouldBe(value);
+ }
}
}
\ No newline at end of file
diff --git a/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs b/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs
index fc23011e..d1b2983c 100644
--- a/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs
+++ b/test/Forest.Contracts.SymbolRegistrar.Tests/SymbolRegistrarContractTests_Buy.cs
@@ -2,6 +2,7 @@
using System.Linq;
using System.Threading.Tasks;
using AElf.Contracts.MultiToken;
+using Google.Protobuf.WellKnownTypes;
using Shouldly;
using Xunit;
@@ -328,5 +329,20 @@ await User1SymbolRegistrarContractStub.RegularSeedRenew.SendAsync(new RegularSee
}
});
}
+
+ [Fact]
+ public async Task BidSeedRenew_Test ()
+ {
+ await Buy_success();
+ await User1SymbolRegistrarContractStub.SetSeedRenewHashVerifyKey.SendAsync(new StringValue{Value = "1a2b3c"});
+ await User1SymbolRegistrarContractStub.BidFinishSeedRenew.SendAsync(new BidFinishSeedRenewInput()
+ {
+ SeedSymbol = "SEED-1",
+ BidFinishTime = DateTime.UtcNow.Second,
+ OpTime = DateTime.UtcNow.Second,
+ RequestHash = "1234"
+ });
+
+ }
}
}
\ No newline at end of file
From a4768ab41f875bc19feb3ee8008d49a7a5630e47 Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Sat, 7 Dec 2024 13:58:21 +0800
Subject: [PATCH 8/9] fix seed suffix check
---
.../SymbolRegistrarContract_Helper.cs | 5 -----
1 file changed, 5 deletions(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
index c5e5acd6..67a4b460 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Helper.cs
@@ -63,11 +63,6 @@ private void AssertSeedSymbolPattern(string symbol)
var symbolPartition = symbol.Split(SymbolRegistrarContractConstants.NFTSymbolSeparator);
Assert(symbolPartition.Length == 2, "Invalid symbol.");
Assert(symbolPartition[0] == SymbolRegistrarContractConstants.SeedPrefixPart, "Invalid seed symbol prefix.");
-
- foreach (var c in symbolPartition[1])
- {
- Assert(c >= '1' && c <= '9', "Invalid seed symbol suffix.");
- }
}
private void AssertPriceListLength(PriceList priceList)
From 55800a6ad28e30c5b08dbbd7f702138b550ae1c1 Mon Sep 17 00:00:00 2001
From: suerlych <19871208@lhcyf>
Date: Sat, 7 Dec 2024 23:28:21 +0800
Subject: [PATCH 9/9] modify hash seq
---
.../SymbolRegistrarContract_Action.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
index f9daf2aa..f92b593d 100644
--- a/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
+++ b/contract/Forest.Contracts.SymbolRegistrar/SymbolRegistrarContract_Action.cs
@@ -299,13 +299,14 @@ public override Empty SpecialSeedRenew(SpecialSeedRenewInput input)
var specialSeed = State.SpecialSeedMap[seedOwnedSymbol];
Assert(specialSeed != null, "Not Special seed " + input.SeedSymbol + " not support renew.");
- var requestStr = string.Concat(input.Buyer.ToBase58(), input.SeedSymbol);
- requestStr = string.Concat(requestStr, input.Price.Symbol, input.Price.Amount, input.OpTime);
+ var requestStr = string.Concat(input.Buyer.ToBase58(), input.SeedSymbol,input.Price.Symbol, input.Price.Amount);
+ requestStr = string.Concat(requestStr,input.OpTime);
CheckSeedRenewRequestHash(requestStr, input.RequestHash);
var lastAddTime = State.SeedRenewTimeMap[input.SeedSymbol];
Assert(input.OpTime > lastAddTime, "Invalid param OpTime");
State.SeedRenewTimeMap[input.SeedSymbol] = input.OpTime;
+
var price = input.Price;
Assert(price != null, "Symbol price not exits");
var priceTokenInfo = GetTokenInfo(price.Symbol);