
Today is the digital era! The millennium of computer technology. One of the hottest topics in this field is the new technology of crypto currencies. Since the day in which Satoshi invented the first crypto currency, the Bitcoin, several thousands of crypto currencies have been created.
Due to the lack of trust as a result of the 2008 global financial crisis, the leading cryptocurrency, Bitcoin, is increasingly thought of as an alternative to the prevailing financial architecture by presenting a technologically more trustworthy alternative. Because of the effect it had due to its number of users, volume, and market size, Bitcoin attracted the attention of the whole world.
By using blockchain technology and mining, cryptucurrencies attempts to replace the services based on trust and the mediation role offered by banks in the traditional finance system. With their characteristics such as low cost, fast transaction times, and low risks, cryptucurrencies first emerged in 2008 and since then, due to these benefits, have triggered an important change and transformation.
Customer attraction has been one of the controversial issues among marketing managers in the current decade. More attraction and satisfaction mean, more success.
The Cryptu Promotion Manager Ecosystem (CryptuProEco®) emphasis on the customer attraction technique in which authors claim it would be the newest with innovation. There are two definitions as promoter and cluster to empower the level of the desired marketing. In this technique, sellers can create their own Services to sell their articles with the help of promoters who may promote the Providers’ articles. So for more information about the project, please read the White Paper!
CryptuProEco® Contract
Cryptu Promotion Manager V1
Smart contract implementation of Cryptu Promotion Manager Ecosystem (CryptuProEco®).
Contract info
Contract name: CryptuPromotionManager
Contract address: 0x5aF6D33DE2ccEC94efb1bDF8f92Bd58085432d2c
View CryptuPromotionManager.sol on BscScan.
View the Promotion Manager Ecosystem White Paper for more information.
Cryptu Promotion Manager Ecosystem Structure
The Promotion Manager Ecosystem, which is invented by Cruptu.io is a novel crypto currency ecosystem (CryptuProEco®), in which sellers (Providers in this context) can create their own Services to sell their goods/services with the help of Promoters who they advertise and promote the Providers's articles.
Each Service consists of Clusters and Promoters. Each Cluster can contain up to 15 Promoters. Promotion Manger Ecosystem structure is shown in Fig. 1.
Fig. 1: Promotion Manager Ecosystem Structure.
The Cluster structure is shown in the Fig. 2.
Fig. 2: Cluster Structure and its Promoters.
Each Promoter can have 2 sub-Promoters with direct connections as shown in the figure. When a Promoter registers in a Service without any referral code, a new Cluster is generated automatically and the Promoter becomes its owner also a referral code is generated and assigned to him/her by the Promotion Manager. The Promoter level is the lowest (4) now. If he gives his referral code to others, and they register in this Service, so they will be added as the children of the first Promoter. If two people added as sub-Promoter of the 1st Promoter, all Promoters would be leveled up, so a Promoter must invite 2 people to be his/her sub-Promoters to upgrade his/her own level. The Promoter can invite others by his/her own referral code.
The topmost Promoter in a full Cluster, would have level 1 (first rank) , so it would benefit of the highest Direct Commission of sales.
The Cluster structure is somehow like a pyramid network marketing, but it has some major differences:
1. Number of members is limited to 15 Promoters, and it is not unlimited like many scamming pyramid marketing networks, in which nothing earned by sub members due to huge number of network members.
2. Nothing paid from sub-Promoters commissions to the upper Promoters. The upper Promoters, just get their own commission from their own direct sale. This is in contrast with pyramid networks, that the top most members take benefit of the lower members' sale commission.
3. Recruiting sub-Promoters by top Promoters, just level them up. So as the Promoters' level grows up, their Direct Commission becomes more. This is why a Promoter needs to add sub-Promoters to himself/herself.
4. Unlike most pyramid networks that don't sell anything but get money from sub members, this ecosystem, don't get any money from Promoters, just Providers pay a registration fee (cash or sale percentage), so there is not anything to be paid by sub-Promoters to the tops.
Direct Commission is calculated based on the sale average of the Promoter per time, for example this average can be daily or any time slice in the order of seconds, This parameter is called AveragingPeriod.
Each Cluster in a Service, has its own Rank, which is based on sale average of its Promoters. According to this sale average, Cluster Rank can be defined. So a Cluster can be ranked up due to its sale average. As the Cluster Rank grows up, its Cluster Commission increases, so every Promoter in this Cluster can benefit of more Cluster Commission than a low rank Cluster. This is the philosophy of making Clusters.
Total Commission (%) = Z1 * F1 + Z2 * F2
F1 = (0.4593 * (PromoterSaleAverage) 2) + (0.4674 * PromoterSaleAverage) + 0.0733 and F1 <= 1
F2 = (ClusterLevelShare [PromoterLevel] * ClusterScore * 0.25);
Default Parameters:
Z1; Direct Commission Weight Factor (Ex: 0.16)
Z2; Cluster Commission Weight Factor (Ex: 0.24)
Promoter Level | ClusterLevelShare |
---|---|
1 | 40% |
2 | 30% |
3 | 20% |
4 | 10% |
ClusterRank | ClusterSaleAverage | ClusterScore |
---|---|---|
1 | 0≤x<0.5 | 20% |
2 | 0.5≤x<1 | 40% |
3 | 1≤x<1.5 | 60% |
4 | 1.5≤x<2 | 80% |
5 | 2≤x | 100% |
All of the above parameters can be set by Providers during Service registration and they can be changed later.
Cluster Rank, is subject to degrade if a Cluster sale average drops during time. So the Promoters must try to sale more to keep their Cluster Rank up. To prevent sudden drop of the Cluster Rank, upon intermittent drop of sale, the clusterRankRelaxationPeriod parameter is defined. It is a period of time that a Cluster Rank would be kept intact, if it sales nothing or a new Promoter added to it. Default value (period) of this parameter is a week in seconds, but it can be set by the Provider to any value up to 6 months.
All data and history of Providers and Promoters can be viewed and changed in the CryptuProEco® dashboard.
The above mentioned ecosystem is developed as an EVM-Based smart contract with the limits of 100 Services that each one can handle 15000 Promoters, organized in 1000 Clusters per Service, according to the limits of available EVMs.
Read/View Functions
getServicesCount
function getServicesCount() notContract external view returns (uint16)
Returns count of registered services.
getServiceStatus
function getServiceStatus(uint16 serviceId) notContract external view returns(ServiceStatus memory)
Returns ServiceStatus structure of the Service using its ID; Read Promotion Manager Ecosystem White Paper for more information.
struct ServiceStatus//10 slots
{
bytes32 name;
uint32 z1;
uint32 z2;
uint32 minDiscount;
uint32 maxDiscount;
bytes32 website;
uint32 clusterRankRelaxationPeriod;
uint32 promoterAveragingPeriod;
//256 bits-1 slot
bool enabled;
uint16 id;
uint16 clustersCount;
uint16 promotersCount;
address creator;
//216 bits -1s lot
uint256 fee;//1 slot
address consumer;
address currency;
address DexRouter;
//480 bits-3 slots
bytes32 providerContact;
ClusterBreak[MAX_CLUSTER_RANK] clusterShare;//480bits-3 lot
uint32[MIN_NODE_LEVEL-1] clusterLevelShare;//128 bits-1slot
}
Item | Type | Description |
---|---|---|
name | bytes32 | Zero padded 32 bytes Service name. |
z1 | uint32 | Direct sale factor percentage. Must be <= 10000 (100%). |
z2 | uint32 | Cluster sale factor percentage. Must be <= 10000 (100%). |
minDiscount | uint32 | Minimum discount of referral codes. Must be < |
maxDiscount | uint32 | Maximum discount of referral codes. Must be > minDiscount |
website | bytes32 | Zero padded 32 bytes Provider's website address. |
clusterRankRelaxationPerid | uint32 | Relaxation period of Clusters in this Service in seconds, Ex: 604800 for 1 week. After passing this period, if a Cluster hasn't sale anything, its rank would be lowered gradually. |
promoterAveragingPeriod | uint32 | Averaging period of a Promoter in seconds. Ex: 86400 for 1 day. Promoter's sale activities are averaged over last time per this period. |
enabled | bool | True, if the Service is enabled. |
id | uint16 | Service unique ID. |
clustersCount | uint16 | Number of Clusters in this Service. |
promotersCount | uint16 | Number of Promoters in this Service. |
creator | address | Address of the Provider's wallet that created this Service. |
fee | uint256 | Paid fee of this Service, if sale percent is selected. |
consumer | address | Consumer contract address. The contract that sells a Service. |
currency | address | Contract address of the token that Consumer used to sell things with it. If 0 supplied, native currency of the network is used, Ex: BNB. |
DexRouter | address | DEX router contract address, used for getting currency price. Can be 0. |
providerContact | bytes32 | Provider's email address. |
clusterShare | ClusterBreak | Array of ClusterBreak structures, defines Cluster ranking stages. See below. |
clusterLevelShare | uint32[4] | Share percentage of each rank of Cluster. Total must be 10000 (100%). |
struct ClusterBreak//96 bits-1 slot
{
uint32 percentage;
uint32 minPurchase;
uint32 maxPurchase;
}
Share percentage, if sale average of a Cluster is >= minPurchase < maxPurchase.
It is a percentage value that is casted into an integer from 0 to 10000. For example, 2156 means 21.56%.
getPromoterStatus
function getPromoterStatus(address wallet,uint16 serviceId) notContract external view returns (PromoterStatus memory)
Returns a PromoterStatus structure (see below) for a Promoter using his/her wallet address in a specified Service, by supplying a wallet address and a Service ID.
Name | Type | Description |
---|---|---|
wallet | address | Promoter's wallet address. |
serviceId | uint16 | ID of the Service. |
struct PromoterStatus{//10
bytes32 contact;// 1 slot
bytes32 serviceName;// 1 slot
uint32 saleCount;
uint16 id;
uint16 parentId;
uint16 clusterId;
uint16 serviceId;
uint8 level;
bytes16 nickName;
bytes10 refCode;//80 bits 1slot
uint256 income;
uint256 totalIncome;
uint256 directCommission;
uint256 clusterCommission;
uint256 saleAverage;
uint256 registrationTime;
}
Item | Type | Description |
---|---|---|
contact | bytes32 | Zero padded 32 bytes email address of the Promoter. |
serviceName | bytes32 | Zero padded 32 bytes Service name, that this Promoter is registered in. |
saleCount | uint32 | How many things the Promoter sold. |
id | uint16 | Promoter's unique ID. |
parentId | uint16 | Parent Promoter's ID. |
clusterId | uint16 | Cluster ID that this Promoter is registered in. |
level | unit8 | Level of this Promoter in its Cluster. 5 is the lowest and 1 is the highest. |
nickName | bytes16 | Zero padded 16 bytes, nick name of the Promoter. Unique over a Service. |
refCode | bytes10 | Zero padded 10 bytes, referral code of the Promoter. |
income | uint256 | Unclaimed income in currency token of the Promoter. |
totalIncome | uint256 | Total income in currency token of the Promoter since registration. |
directCommission | uint256 | Direct sale commission percentage of the Promoter, casted into integer. |
clusterCommission | uint256 | Cluster ranking commission of the Promoter, casted into integer. |
saleAverage | uint256 | Sale average of the Promoter over time per averaging period of the Service. |
registrationTime | uint256 | Time stamp of the Promoter registration. |
getPromotersStatus
function getPromotersStatus(uint16 serviceId,uint16 cursor,uint16 count) external view returns (PromoterStatus[] memory _ps)
Returns array of PromoterStatus structure, using serviceId, cursor and count parameters. Refer getPromoterStatus function for more information.
getPromoterServices
function getPromoterServices(address wallet) external view returns ( uint16[] memory registeredServices)
Returns array of Service IDs, in which the wallet address is registered as a Promoter.
Name | Type | Description |
---|---|---|
wallet | address | Promoter's wallet address. |
getProviderServices
function getProviderServices(address wallet) external view returns (uint16[] memory)
Returns an array of Service IDs according to a wallet address, this address must be a Provider wallet address.
Name | Type | Description |
---|---|---|
wallet | address | Provider's wallet address. |
getCodeDiscount
function getCodeDiscount(bytes10 refCode) external view returns (uint256)
Returns value of discount according to the supplied referral code. The return value is a percentage casted into uint256, from 0 to 10000 (100%).
Name | Type | Description |
---|---|---|
refCode | address | Zero padded 10 bytes, referral code of the Promoter. |
getCodeCommission
function getCodeComission(bytes10 refCode) external view returns (uint256,uint256)
Returns sum of direct and Cluster commissions of a Promoter due to the supplied referral code as the first return parameter.
The second return value is the percentage of Service fee that must be paid by the Consumer contract if the Provider selected the Service registration fee to be paid as sale percentage, but if the Provider selected cash method, the value is 0.
Return values are percentages casted into uint256, from 0 to 10000 (100%).
Name | Type | Description |
---|---|---|
refCode | address | Zero padded 10 bytes, referral code of the Promoter. |
Write Functions (Promoter)
registerPromoter
function registerPromoter(uint16 serviceId ,bytes10 refCode,bytes32 contact,bytes16 nickName) external notContract
A Promoter can register itself in an arbitrary Service, by calling this function. If refCode is not supplied (set to 0), serviceId parameter is mandatory, in this way a new Cluster will be created and the Promoter will be set as the owner of this Cluster in the Service.
Upon supplying a refCode, serviceId parameter is ignored and the Promoter will be registered in the proper Service and Cluster that is specified by the refCode if the parent Promoter has enough capacity to accept it.
If the parent Promoter has no capacity or the Promoter is already registered by its wallet address or the supplied nick name exists, the function will revert!
Name | Type | Description |
---|---|---|
serviceId | uint16 | ID of the Service. |
refCode | bytes10 | Zero padded 10 bytes, referral code of the Promoter. |
contact | bytes32 | Optional; 32 bytes, zero padded email address of the Promoter. It is better to be encrypted due to user privacy. |
nickName | bytes16 | Zero padded 16 bytes, nick name of the Promoter. The supplied nick name must be unique in a Service. |
changePromoterContact
function changePromoterContact(bytes10 refCode,bytes32 contact) external
Changes the Promoter's email address if necessary, using its referral code. Must be called from the Promoter's wallet address otherwise it will revert!
Name | Type | Description |
---|---|---|
refCode | bytes10 | Zero padded 10 bytes, referral code of the Promoter. |
contact | bytes32 | 32 bytes, zero padded email address of the Promoter. It is better to be encrypted due to user privacy. |
withdrawIncome
function withdrawIncome(uint16 serviceId) external nonReentrant notContract
By calling this function, the Promoter can withdraw all of his/her income according to the supplied serviceId, in a single transaction. Must be called from the Promoter's wallet address otherwise it will revert!
Write Functions (Provider/Consumer)
registerServiceAndConsumer
function registerServiceAndConsumer(bytes32 serviceName,address consumer,
ClusterBreak[5] calldata share,
uint32[MIN_NODE_LEVEL-1] calldata levelShare,
uint32 z1,uint32 z2,uint32 minDiscount,uint32 maxDiscount,
uint32 clusterRelaxationPeriod,
uint32 promoterAveragingPeriod,address currency,ServiceExtra calldata extra) external
payable nonReentrant notContract
A Provider can create a new Service by calling this function. Emits OnServiceRegistered event. Read CryptuProEco® White Paper for more information.
Consumer contract must be a verified contract, so the Promotion Manager Ecosystem's administrators would check the contract code, if a bug or scam is detected, they are eligible to disable the Service without any prior notification!
If the currency token is a liquidity generator contract type or it applies any type of taxes on transactions, it is very important to exclude both, Consumer contract and Promotion Manager Contract from fee/tax, prior to register a Service, otherwise your Promoters would not be able to withdraw their incomes!
Name | Type | Description |
---|---|---|
serviceName | bytes32 | Zero padded 32 bytes Service name. Name must be unique in the Promotion Manager Ecosystem otherwise it reverts. |
consumer | address | Address of the Consumer contract, which will use the Promotion Manager Ecosystem. Consumer contract must be a verified contract, so the Promotion Manager Ecosystem's owners would check the contract code, if a bug or scam is detected, they are eligible to disable the Service without any prior notification! |
share | ClusterBreak[5] | Array of ClusterBreak structures, defines Cluster ranking stages. See ClusterBreak. |
levelShare | uint32[4] | Share percentage of each rank of Cluster. Total must be 10000 (100%). |
z1 | uint32 | Direct sale factor percentage. Must be <= 10000 (100%). |
z2 | uint32 | Cluster sale factor percentage. Must be <= 10000 (100%). |
minDiscount | uint32 | Minimum discount of referral codes. Must be < maxDiscount. |
maxDiscount | uint32 | Maximum discount of referral codes. Must be > minDiscount. |
clusterRankRelaxationPerid | uint32 | Relaxation period of Clusters in this Service in seconds, Ex: 604800 for 1 week. After passing this period, if a Cluster hasn't sale anything, its rank would be lowered gradually. |
promoterAveragingPeriod | uint32 | Averaging period of a Promoter in seconds. Ex: 86400 for 1 day. Promoter's sale activities are averaged over last time per this period. |
currency | address | Contract address of the token that Consumer used to sell things with it. If 0 supplied, native currency of the network is used, Ex: BNB. |
extra | ServiceExtra | A ServiceExtra structure for Service optional values |
struct ServiceExtra
{
address DexRouter;
bytes32 website;
bytes32 providerContact;
}
Name | Type | Description |
---|---|---|
DexRouter | address | Optional; DEX router contract address, used for getting currency price. Can be 0. |
website | bytes32 | Optional; Zero padded 32 bytes Provider's website address. |
providerContact | bytes32 | Optional; Zero padded 32 bytes Provider email address. |
changeServiceParameters
function changeServiceParameters(uint16 serviceId,address consumer,
ClusterBreak[5] calldata share,
uint32[MIN_NODE_LEVEL-1] calldata levelShare,
uint32 z1,uint32 z2,uint32 minDiscount,
uint32 maxDiscount,
uint32 clusterRelaxationPeriod,
uint32 promoterAveragingPeriod,
ServiceExtra calldata extra) external nonReentrant notContract
Provider can change its own Service by calling this function. Caller wallet address must be the Provider's wallet address, otherwise it reverts!
Name | Type | Description |
---|---|---|
serviceId | unit16 | Service ID. |
consumer | address | Address of the Consumer contract, which will use the Promotion Manager Ecosystem. Consumer contract must be a verified contract, so the Promotion Manager Ecosystem's owners would check the contract code, if a bug or scam is detected, they are eligible to disable the Service without any prior notification! |
share | ClusterBreak[5] | Array of ClusterBreak structures, defines Cluster ranking stages. See ClusterBreak. |
levelShare | uint32[4] | Share percentage of each rank of Cluster. Total must be 10000 (100%). |
z1 | uint32 | Direct sale factor percentage. Must be <= 10000 (100%). |
z2 | uint32 | Cluster sale factor percentage. Must be <= 10000 (100%). |
minDiscount | uint32 | Minimum discount of referral codes. Must be < maxDiscount. |
maxDiscount | uint32 | Maximum discount of referral codes. Must be > minDiscount. |
clusterRankRelaxationPerid | uint32 | Relaxation period of Clusters in this Service in seconds, Ex: 604800 for 1 week. After passing this period, if a Cluster hasn't sale anything, its rank would be lowered gradually. |
promoterAveragingPeriod | uint32 | Averaging period of a Promoter in seconds. Ex: 86400 for 1 day. Promoter's sale activities are averaged over last time per this period. |
extra | ServiceExtra | A ServiceExtra structure for Service optional values |
useCode
function useCode(bytes10 refCode,uint32 buyCount, uint256 commissionAmount,uint256 fee) external nonReentrant;
Just Consumer contract call this function, in order to inform the Promotion Manager Ecosystem, that a successful buy operation is finished. It emits OnCodeUsed event.
The Consumer contract, must report refCode used, buy count of goods/service, transferred commission amount of the Promoter, transferred fee amount of the Promotion Manager Ecosystem (if sale percent is selected at Service registration time). Before calling this function, Consumer contract must transfer Promoter's commission amount and Promotion Manager Ecosystem's fee (if sale percent is selected at Service registration time), to the Promotion Manager contract.
Consumer contract must be a verified contract, so the Promotion Manager Ecosystem's owners would check the contract code, if a bug or scam is detected, they are eligible to disable the Service without any prior notification!
If the currency token is a liquidity generator contract type or it applies any type of taxes on transactions, it is very important to exclude both, Consumer contract and Promotion Manager contract from fee/tax prior to register a Service, otherwise your Promoters would not be able to withdraw their incomes!
Name | Type | Description |
---|---|---|
refCode | bytes10 | Zero padded 10 bytes, referral code of the Promoter. |
buyCount | uint32 | Count of sold goods/service. |
commissionAmount | uint256 | Transferred amount of Promoter's commission. |
fee | uint256 | Transferred amount of Promotion Manger Ecosystem fee (if sale percent is selected at Service registration time), otherwise it is 0. |
Write Functions (Owner)
setServiceRegistrationParams
function setServiceRegistrationParams(uint256 fee,uint32 feePercent,address feeReceiver ) external onlyOwner
Promotion Manager Ecosystem’s owner can set the Service registration fee (for cash option), fee percent (for sale percentage option) and fee receiver address.
Name | Type | Description |
---|---|---|
fee | uint256 | Service registration fee in Wei. |
feePercent | uint32 | Fee percentage, (0 to 10000). |
feeReceiver | address | Fee receiver address. |
enableService
function enableService(uint16 serviceId) external onlyOwner
Promotion Manager Ecosystem’s owner can enable a Service every time.
Name | Type | Description |
---|---|---|
serviceId | uint16 | Service ID. |
disableService
function disableService(uint16 serviceId) external onlyOwner
Promotion Manager Ecosystem’s owner can disable a Service every time.
Name | Type | Description |
---|---|---|
serviceId | uint16 | Service ID. |
findService
function findService(bytes32 serviceName) external view onlyOwner returns (uint16)
Promotion Manager Ecosystem’s owner can use this function to find Service ID by its name.
Name | Type | Description |
---|---|---|
serviceName | bytes32 | Zero padded 32-bytes Service name. |
withdrawFee
function withdrawFee(uint16 serviceId) external onlyOwner
Promotion Manager Ecosystem’s owner can withdraw the collected Service registration fee.
Emits OnFeeWithdrawn event.
Name | Type | Description |
---|---|---|
serviceId | uint16 | Service ID. |
setPromotionManagerLimits
function setPromotionManagerLimits(uint16 maxServiceCount,uint16 maxClusterCount,uint16 maxPromoterCount) external onlyOwner
Promotion Manager Ecosystem’s owner can change the Promotion Manager Ecosystem size upon the network condition. Use it carefully! Check all current Services, Clusters and Promoters count.
Name | Type | Description |
---|---|---|
MaxServiceCount | uint16 | Maximum Services count can be created on the Promotion Manager Ecosystem. Default: 100. |
maxClustersCount | uint16 | Maximum Clusters count can be created per Service on the Promotion Manager Ecosystem. Default: 1000. |
maxPromoterCount | uint16 | Maximum Promoters count can be created per Service on the Promotion Manager Ecosystem. Default: 15000. |
Events (Promoter)
OnPromoterRegistered
event OnPromoterRegistered(bytes10 referralCode);
Promoter is registered.
Emitter: registerPromoter.
OnIncomeWithdrawn
event OnIncomeWithdrawn(address wallet,address currency,uint256 amount);
Promoter withdrew his/her income successfully.
Emitter: withdrawIncome.
Events (Provider)
OnServiceRegistered
event OnServiceRegistered(uint256 serviceId);
Provider registered a new Service.
Emitter: registerServiceAndConsumer.
OnCodeUsed
event OnCodeUsed(bytes10 refCode, uint256 clusterTotalSale,uint256 clusterSaleAverage,uint256 clusterScore);
Referral code used to buy goods/services.
Emitter: useCode.
Events (Owner)
OnFeeWithdrawn
event OnFeeWithdrawn(address currency,uint256 amount);
Service registration fee is withdrawn.
Emitter: withdrawFee.
Contract Roles
Role | Description |
---|---|
Owner (onlyOwner) | The Promotion Manager smart contract owner. |
Promoter | A person with a wallet address that wants to be a Promoter in Promotion Manager Ecosystem. Every goods/services that be sold by the Promoter's referral code, make some income for him/her according to the selected Service. |
Provider | A person/company with a wallet address, which wants his/her/its goods/services to be sold by promoters. |
Consumer | A smart contract that is developed by the Provider to sell goods/services on a smart chain using an interface to the Promotion Manager smart contract. |
Buyer | A person with a wallet address that wants to buy goods/services from Provider by using a Promoter's referral code, upon using this code he/she benefits from discount. A buyer interacts with the Consumer smart contract. |
Role Description
Owner
0xad9d97fc7bf0ac6dc68d478dcb3709454519b358
Address controlled by gnosis multisignature contract with a threshold of 3/4
Functions
registerServiceAndConsumer - Provider
function registerServiceAndConsumer(bytes32 serviceName,address consumer,
ClusterBreak[5] calldata share,uint32[MIN_NODE_LEVEL-1] calldata levelShare,
uint32 z1,uint32 z2,uint32 minDiscount,uint32 maxDiscount, uint32 clusterRelaxationPeriod,
uint32 promoterAveragingPeriod,address currency,ServiceExtra calldata extra) external payable nonReentrant notContract
{
bool _payETH;
{//scope: checks
//adding service and its operartor
require( _currentServiceId<=_maxServiceCount,"Too many services!");
require(serviceName!=0,"Service name not supplied!");
require((z1<=10000)&&(z2<=10000),"Invalid z1 or z2!");
require(maxDiscount<= MAX_SERVICE_DISCOUNT,"Discount exceeds limit!");
require(maxDiscount>minDiscount,"Max discount< Min discount!");
require(((clusterRelaxationPeriod>=MIN_TIME_SLICE)&&(clusterRelaxationPeriod <=MAX_RELAXATION_PERIOD)),
"clusterRelaxationPeriod not in range!");
require((promoterAveragingPeriod>=MIN_TIME_SLICE),"promoterAveragingPeriod not in range!");
uint _totalShare;
for(uint i;i<(MIN_NODE_LEVEL-1);)
{
_totalShare+=levelShare[i];
unchecked{++i;}//gas opt
}
require(_totalShare==10000,"Total level shares != 10000!");
require(share[0].percentage<=10000,"Cluster share values > 10000!");
require(share[1].percentage<=10000,"Cluster share values > 10000!");
require(share[2].percentage<=10000,"Cluster share values > 10000!");
require(share[3].percentage<=10000,"Cluster share values > 10000!");
require(share[4].percentage<=10000,"Cluster share values > 10000!");
require(share[0].maxPurchase>share[0].minPurchase,"MaxPurchase < MinPurchase!");
require(share[1].maxPurchase>share[1].minPurchase,"MaxPurchase < MinPurchase!");
require(share[2].maxPurchase>share[2].minPurchase,"MaxPurchase < MinPurchase!!");
require(share[3].maxPurchase>share[3].minPurchase,"MaxPurchase < MinPurchase!");
require(share[4].maxPurchase>share[4].minPurchase,"MaxPurchase < MinPurchase!");
}
uint16 _serviceId =_findServiceByName(serviceName);// (stringToBytes32(serviceName));
if (_serviceId!=0)//the service is regestered before
{
//no thing to do
revert("Service already exists!");
}else // no such a this service is registered
{
//provider selected the ETH payment method
//this is a new service creation so the caller must pay the registration Fee
if(msg.value!=0)
{
_payETH=true;
require(msg.value==_serviceRegistrationFee,"Service registration fee is not enough!");
//transfering to fee receiver
payable(_feeReceiver).transfer(_serviceRegistrationFee);
}
_currentServiceId=_lowgas_inc(_currentServiceId);// gas opt
_providers[msg.sender].wallet=msg.sender;//add this as new provider that owns this service
_providers[msg.sender].serviceIds.push(_currentServiceId);//by array
Service storage _newService=_services[_currentServiceId];
_newService.id=_currentServiceId;
_newService.registered=true;
_newService.enabled=true;
_newService.name=serviceName;
_newService.creator=msg.sender;//set the caller as the service creator
//adding the consumer
_newService.consumer=consumer;
_newService.clustersCount=0;
//coping cluster share values
_newService.clusterShare[1]=share[0];
_newService.clusterShare[2]=share[1];
_newService.clusterShare[3]=share[2];
_newService.clusterShare[4]=share[3];
_newService.clusterShare[5]=share[4];
//copying cluster level share values
for(uint8 i=1;i<(MIN_NODE_LEVEL);)
{
_newService.clusterLevelShare[i]=levelShare[i-1];
unchecked{++i ;}//gas opt
}
//setting z factors
_newService.z1=z1;
_newService.z2=z2;
//setting disounts
_newService.minDiscount=minDiscount;
_newService.maxDiscount=maxDiscount;
_newService.promoterAveragingPeriod=promoterAveragingPeriod;
_newService.clusterRankRelaxationPeriod=clusterRelaxationPeriod;
_newService.currency=currency;
_newService.payETH=_payETH;
_newService.DexRouter=extra.DexRouter;
_newService.website=extra.website;
_newService.providerContact=extra.providerContact;
emit OnServiceRegistered(_currentServiceId);
}
}
A Provider, calls this function by his/her wallet to create a Service on the Cryptu Promotion Manager Ecosystem (CryptuProEco®).
changeServiceParameters - Provider
function changeServiceParameters(uint16 serviceId,address consumer,
ClusterBreak[5] calldata share,uint32[MIN_NODE_LEVEL-1] calldata levelShare,
uint32 z1,uint32 z2,uint32 minDiscount,uint32 maxDiscount, uint32 clusterRelaxationPeriod,
uint32 promoterAveragingPeriod,
ServiceExtra calldata extra) external nonReentrant notContract
{
require(_isServiceRegistered(serviceId),"Invalid service Id!");
Service storage _currentService=_services[serviceId];
{//scope: checks
require(_currentService.creator==msg.sender,"Unauthorized!");
// require(serviceName!=0,"Service name not supplied!");
require((z1<=10000)&&(z2<=10000),"Invalid z1 or z2!");
require(maxDiscount<= MAX_SERVICE_DISCOUNT,"Discount exceeds limit!");
require(maxDiscount>minDiscount,"Max discount< Min discount!");
require(((clusterRelaxationPeriod>=MIN_TIME_SLICE)&&(clusterRelaxationPeriod <=MAX_RELAXATION_PERIOD)),"clusterRelaxationPeriod not in range!");
require((promoterAveragingPeriod>=MIN_TIME_SLICE),"promoterAveragingPeriod not in range!");
uint256 _totalShare;
for(uint256 i;i<(MIN_NODE_LEVEL-1);)
{
_totalShare+=levelShare[i];
unchecked{++i;}
}
require(_totalShare==10000,"Total level shares != 10000!");
require(share[0].percentage<=10000,"Cluster share values > 10000!");
require(share[1].percentage<=10000,"Cluster share values > 10000!");
require(share[2].percentage<=10000,"Cluster share values > 10000!");
require(share[3].percentage<=10000,"Cluster share values > 10000!");
require(share[4].percentage<=10000,"Cluster share values > 10000!");
require(share[0].maxPurchase>share[0].minPurchase,"MaxPurchase < MinPurchase!");
require(share[1].maxPurchase>share[1].minPurchase,"MaxPurchase < MinPurchase!");
require(share[2].maxPurchase>share[2].minPurchase,"MaxPurchase < MinPurchase!");
require(share[3].maxPurchase>share[3].minPurchase,"MaxPurchase < MinPurchase!");
require(share[4].maxPurchase>share[4].minPurchase,"MaxPurchase < MinPurchase!");
}
//checks provider existance
//set the consumer contract address
_currentService.consumer=consumer;
//copying cluster share values
_currentService.clusterShare[1]=share[0];
_currentService.clusterShare[2]=share[1];
_currentService.clusterShare[3]=share[2];
_currentService.clusterShare[4]=share[3];
_currentService.clusterShare[5]=share[4];
//copying cluster level share values
for(uint8 i=1;i<(MIN_NODE_LEVEL); )
{
_currentService.clusterLevelShare[i]=levelShare[i-1];
unchecked{++i;}//gas opt
}
_currentService.z1=z1;
_currentService.z2=z2;
//setting disounts
_currentService.minDiscount=minDiscount;
_currentService.maxDiscount=maxDiscount;
_currentService.promoterAveragingPeriod=promoterAveragingPeriod;
_currentService.clusterRankRelaxationPeriod=clusterRelaxationPeriod;
_currentService.DexRouter=extra.DexRouter;
_currentService.website=extra.website;
_currentService.providerContact=extra.providerContact;
//currency is not changeable
}
The changeServiceParameters can be called by a Provider to change its Service parameters.
useCode – Provider
function useCode(bytes10 refCode,uint32 buyCount, uint256 commissionAmount,uint256 fee) external nonReentrant
{
//updates the state of PM due to service sales
//checking code validity
Referral memory _referral= _referrals[refCode];
require ((_referral.serviceId!=0),"Invalid code!");//gas opt
require ((_referral.clusterId!=0),"Invalid code!");
require((_referral.promoterId!=0),"Invalid code!");
require(_services[_referral.serviceId].consumer==msg.sender,"Invalid consumer!");//gas opt
require(_services[_referral.serviceId].enabled,"Service disabled!");
//getting service, cluster and promoter
Service storage _currentService = _services[_referral.serviceId];
Cluster storage _currentCluster=_currentService.clusters[_referral.clusterId];
Promoter storage _currentPromoter=_currentService.promoters[_referral.promoterId];
//increasing the payed fee value of this service
_currentService.fee=_lowgas_add_256(_currentService.fee,fee); //_currentService.fee+=fee;
_currentPromoter.income=_lowgas_add_256(_currentPromoter.income,commissionAmount);
_currentPromoter.totalIncome= _lowgas_add_256(_currentPromoter.totalIncome,commissionAmount);
//increase the sale count of this promoter
_currentPromoter.saleCount=_lowgas_add_32(_currentPromoter.saleCount,buyCount);
//increase total sale of this cluster
_currentCluster.totalSale=_lowgas_add_32( _currentCluster.totalSale,buyCount);
//updating direct sale percentage
//z1*f1
( _currentPromoter.directCommission,_currentPromoter.saleAverage)=(_calcPromoterDirectCommission(_currentService, _currentPromoter));
//updating promoter's cluster commission
uint256 _saleAverage;
uint8 _rank;
(_currentPromoter.clusterCommission ,_saleAverage ,_rank)=_calcPromoterClusterComission(_currentService,_currentCluster,
_currentPromoter);
//the cluster section
//gas opt-less gas
uint256 _clusterScore= _updateClusterRankAndAverage2(_currentService,_currentCluster, _saleAverage, _rank);
emit OnCodeUsed(refCode,_currentCluster.totalSale,_currentCluster.saleAverage,_clusterScore);
}
A Provider must call this function in the Buy function of his/her Consumer contract to tell the Promotion Manager, that goods/services have been sold by a Promoter referral code. For more information see: How to Implement Promotion Manager in My Consumer Contract.
registerPromoter – Promoter
function registerPromoter(uint16 serviceId ,bytes10 refCode,bytes32 contact,bytes16 nickName) external notContract
{
require(_currentServiceId!=0,"No service registered!");
require(_services[serviceId].enabled,"Service disabled!");
bytes10 _code;
_code = _registerPromoter(serviceId,refCode,contact,nickName);
emit OnPromoterRegistered(_code);
}
Callable by a Promoter to register himself/herself in a Service.
changePromoterContact – Promoter
function changePromoterContact(bytes10 refCode,bytes32 contact) external
{
//changes a promoter's contact data
Referral memory _referral=_referrals[refCode]; //checking the validity of ref code
require ((_referral.serviceId!=0)&&(_referral.clusterId!=0)&&(_referral.promoterId!=0),"Invalid code!");
//it is a valid code
Service storage _currentService = _services[_referral.serviceId];
Promoter storage _currentPromoter=_currentService.promoters[_referral.promoterId];
require(_currentPromoter.wallet==msg.sender,"Not authorized!");
_currentPromoter.contact=contact;//set the contact data
}
For a registered Promoter to change his/her email address. For privacy, it is recommended to send encrypted email address into this function that is not readable by others in the block explorer of the smart chain!
withdrawIncome – Promoter
function withdrawIncome(uint16 serviceId) external nonReentrant notContract
{
//promoter claims his/her own income
require(_isServiceRegistered(serviceId),"Invalid service Id!");
Service storage _currentService=_services[serviceId];
require (_isPromoterRegistered(_currentService,msg.sender),"Not registered in this service!");
Promoter storage _currentPromoter= _currentService.promoters[_currentService.wallets[msg.sender].promoterId];
require(_currentPromoter.income!=0,"Nothing to withdraw!");
uint256 _amount= _currentPromoter.income;
//setting the income to 0
_currentPromoter.income=0;
//Transfer money to msg.sender
if (_currentService.currency==address(0))
{
//native
address payable _to= payable(msg.sender);
(bool sent,) = _to.call{value: _amount}("");
require(sent, "Failed to send Ether");
}else
{
//token
IERC20 _currencyToken=IERC20(_currentService.currency);
_currencyToken.safeTransfer(msg.sender, _amount);
}
emit OnIncomeWithdrawn(msg.sender,_currentService.currency,_amount) ;
}
A registered Promoter can call this function from the wallet used to register himself/herself, to withdraw the income of promotions.
setServiceregistrationParams – Owner
function setServiceRegistrationParams(uint256 fee,uint32 feePercent,address feeReceiver ) external onlyOwner
{
//sets the service registration fee and receiver address
_setServiceRegistrationParams(fee,feePercent, feeReceiver);
}
Only the Owner of Promotion Manager contract can call this function to change the Service registration fee parameters.
enableService – Owner
function enableService(uint16 serviceId) external onlyOwner
{
//enables the service
require(_services[serviceId].registered,"Service not registered!");
_services[serviceId].enabled=true;
}
The Owner can enable a registered Service.
disableService – Owner
function disableService(uint16 serviceId) external onlyOwner
{
//disables the service
require(_services[serviceId].registered,"Service not registered!");
_services[serviceId].enabled=false;
}
The Owner can disable a registered Service.
findService – Owner
function findService(bytes32 serviceName) external view onlyOwner returns (uint16)
{
//owner can find service id by name
return _findServiceByName(serviceName);
}
The Owner can find a registered Service ID, by its name.
withdrawFee – Owner
function withdrawFee(uint16 serviceId) external onlyOwner
{
//promoter claims his/her own income
require(_isServiceRegistered(serviceId),"Invalid service Id!");
Service storage _currentService=_services[serviceId];
require (_currentService.fee!=0,"Nothing to withdraw!");
uint256 _amount= _currentService.fee;
//setting the fee to 0
_currentService.fee=0;
// Transfer money to msg.sender
if (_currentService.currency==address(0))
{
//native
address payable _to= payable(msg.sender);
(bool sent,) = _to.call{value: _amount}("");
require(sent, "Failed to send Ether");
}else
{
//token
IERC20 _currencyToken=IERC20(_currentService.currency);
_currencyToken.safeTransfer(msg.sender, _amount);
}
emit OnFeeWithdrawn(_currentService.currency,_amount) ;
}
The Owner can withdraw the collected Service registration fee.
setPromotionManagerLimits- Owner
function setPromotionManagerLimits(uint16 maxServiceCount,uint16 maxClusterCount,uint16 maxPromoterCount) external onlyOwner
{
//sets service, cluster , promoters max count
//use it carefully!
require(_maxServiceCount>=_currentServiceId,"Current service count is more!");
_maxServiceCount=maxServiceCount;
_maxClusterCount=maxClusterCount;
_maxPromoterCount=maxPromoterCount;
}
The Owner can set the maximum size of the Promotion Manager Ecosystem.
How to Implement Promotion Manager in My Consumer Smart Contract?
1- Adding ICryptuPromotionManager Interface
Your Consumer contract must import the ICryptuPromotionManager.sol like the below code:
Import "ICryptuPromotionManager. Sol";
Then, add below code to the Consumer contract body, in its public section, to define instance of Promotion Manager contract and its interface:
contract Tester is ReentrancyGuard,Ownable{
//testbench for CryptuPromotionManager
address private _promotionManager;
address private _currency;
ICryptuPromotionManager public promotionManager;//Promotion Manager Interface
IERC20 public currencyToken;// Interafce of currency token
Add Promotion Manager contract address parameter into Consumer contract constructor body, or define it statically in your code:
constructor (address promoManager,address currency) Ownable(msg.sender)
{
_currency=currency;//currency token address that you want to sell your goods/services by it, If you want to sell by native currencies(ETH,BNB,…) just pass 0;
_promotionManager=promoManager;//put Promotion Manager address to private variabe.
//set the intaerface to the address
promotionManager=ICryptuPromotionManager(_promotionManager);
}
2- Using the Promotion Manager Interface
The Consumer contract, must have a Buy function, for example this function is buyService, and your customers call this function by their wallets to purchase something from your store. To use Promotion Manager feature in your Consumer contract, your Buy function must pass the referral code parameter like this:
function buyService(uint32 count,bytes32 refCode) external payable
Purchase page of your store website must have a referral code text box, in which, your customer can enter their referral code to get some discount. Your website code must convert that referral code into 10 Bytes code and pass it to the Buy function by web3 interface of MetaMask™ wallet. Java Script code snippet to do it:
function zeroLeading(str,count)
{
var pad=new String;
return pad.padStart(count-str.length,'0')+str
}
function encodeRefCode(strcode)
{
let arr=strcode.split("-")
let r
if(arr.length==4)
{
let s=Number(arr[0]).toString(16)
s=zeroLeading(s,4)
let c=Number(arr[1]).toString(16)
c=zeroLeading(c,4)
let p=Number(arr[2]).toString(16)
p=zeroLeading(p,4)
let code=Number(arr[3]).toString(16)
code=zeroLeading(code,8)
r="0x"+s+c+p+code
}
else
r="0x00000000000000000000"
return r
}
A referral code has below format:
ServiceID-ClusterID-PromoterID-RandomCode
For example: 1-1-1-351687
This code must be packed into a Bytes10 variable (Ex: 0x00010001000100155ef3) and then be passed to the Buy function, so the above JS snippet, can do it for you.
The Buy function body must have the below code in its body. It should be payable if you want to use native currencies (ETH, BNB, etc.):
function buyService(uint32 count,bytes32 refCode) external payable
{
uint256 _amount=count*SERVICE_PRICE;//your goods/services cost
/*asking the Promotion Manager, how much commission must be paid to the Promoter, who his/her referral code is used
in this purchase and if there must be a service registration fee to be paid to the Promotion Manager Ecosystem*/
(uint256 _promoterPercent, uint256 _feePercent)=promotionManager.getCodeComission(refCode);
//getting commision percentage from te PM
//calculatiing the amount of Promoter commission
uint256 _promoterCommission=(_promoterPercent*_amount)/10000;
//calculatiing the amount of service registration fee(if you want to pay the fee by your sale percentage, otherwise this value is 0)
uint256 _fee=(_feePercent*_amount)/10000;
if (_currency==address(0))
{
//for native currencies only
//if you use token currencies, remove these lines
/********************************************************************/
//transfering buy amount into this contract
require(_amount==msg.value,"Not enough ETH payed!");
//transfering the Promoter commission to the Promotion Manager
address payable _to= payable(_promotionManager);
(bool _sent,) = _to.call{value:_promoterCommission}("");
require(_sent, "Failed to send commission");
if(_fee!=0)
{
//there is a service registration fee that must be paid from sale amount
(_sent,) = _to.call{value:_fee}("");
require(_sent, "Failed to send fee!");
}
/********************************************************************/
}else
{
//for token currencies
//if you use native currencies (ETH, BNB,...), remove these lines
/********************************************************************/
//transfering buy amount into this contract
currencyToken.safeTransferFrom(address(msg.sender), address(this), _amount);
//transfering the Promoter commission to PM
currencyToken.safeTransfer(_promotionManager, _promoterCommission);
if(_fee!=0)
{
//there is a service regitration fee that must be paid from sale amount
//transfering fee to the Promotion Manager
currencyToken.safeTransfer(_promotionManager, _fee);
}
/********************************************************************/
}
/*using the referral code, the consumer must call the Promotion Manager useCode function after
finishing the commission and fee transfers*/
promotionManager.useCode(refCode,count,_promoterCommission,_fee);
//emitting the event
emit OnCommisionTransfered
}
Attention: Consumer contract must be a verified contract, so the Promotion Manager Ecosystem’s administrators would check the contract code, if a bug or scam is detected, they are eligible to disable the Service without any prior notification!
CryptuProEco® or Cryptu Promotion Ecosystem is an unique, professional and comprehensive platform under Cryptu.io without any other example in the crypto world that you may enter it for services or promoters which will be described later. In this platform, the INCOME is the GOAL. If you have a business, you may think of merchandising or extending. Else you may want to introduce others and receive your COMMISSION.
Two fundamental sections of the CryptuProEco® consist of services and promoters. In other word if you have your own business, you may register as a new service else you may would like to register as a new promoter.
Promoter
The promoters are the people who try to reach potential investors. Indeed, they increase excitement surrounding investment and generate additional revenue.
Service
In a word, a service is a business. The owner of a company may like to extend his/her business. You can register your company/business as a service and reach the top promoters. They can help you to absorb the customers, so your revenue will be promoted. Then you should pay the promoters’ commission.
The main part of our platform has been named “Promotion Manager”. The first step is to connect your wallet (Fig. 1). Our registration is free of charge for the promoters.
Fig. 1: Connecting Wallet.
You may see a column in the left-hand side of the CryptoProEco® webpage. The first item is “Tops“ (Fig. 2).
Fig. 2: Tops.
This item has two sub-items:
• Top Services (Providers)
• Top Promoters
Top Services
The top services may be seen in Fig. 3. This table shows the list of businesses which are registered in the CryptuProEco® and they are sorted based on their ranks.
Fig. 3: Top Services.
The shown top services table consist of several columns as described in the following table:
Column Title | Description |
---|---|
Name | The name (or title) of the service or business is written here. |
Rank | The level of the desired service may be shown in the rank place based on total sale count. |
Sale Count | The amount of the providers’ articles that is traded in the CryptuProEco®. |
Total Income ($) | The revenue of the top services in $ till now. |
Total Income (Crypto) | The revenue of the top services in cryptocurrency till now by the currencies in which they are acceptable by the providers. These currencies are set during the service registration (refer sec. 5-11). |
Promoter Count | The number of the promoters in which they are trying to reach investors and/or the customers for the desired top services. |
Currency | The acceptable currency of the desired top services. |
Website | The website of the top services in which registered in the CryptuProEco®. |
Top Promoters
In this section, the list of top promoters is shown as Fig. 4. The table shows the top promoters’ situation which are registered in the CryptuProEco®
Fig. 4: Top Promoters.
The shown top promoters table consist of several columns as described in the following table:
Column Title | Description |
---|---|
Nickname | The title that each promoter has chosen for themselves during the registration period. |
Level | The level of each promoter is specified by his/her activity (Refer to the CryptuProEco® White Paper). |
Sale Average | The average of the sold products by the promoter per each month. |
Sale Count | The amount of the articles that is traded by each promoter. |
Income ($) | The income of each promoter in $. |
Income (Crypto) | The income of each promoter in Cryptocurrency. |
Commission (%) | Percentage of the receiving commission of each promoter from the total commission. |
Register New Promoter
Each promoter should have been registered at the beginning. Their information must enter in the CryptuProEco® related section (Fig. 5). These fields should fill very carefully by each promoter.
Fig. 5: Register New Promoter.
New promoter registration consist of fields as described in the following table:
Field Title | Description |
---|---|
Service | The kind of service is selected here. If you are the first promoter of a business, you will choose that specific company (or business). Else and if other promoter has introduced a business, so you will have a referral code and you should enter it in the related box. So, you will be the other promoter of that introduced business automatically and you are completing the cluster with others (Refer to the CryptuProEco® White Paper). |
Referral | The referral code that you have received from other promoters and your team (you and other promoters) are trying to complete a cluster (Refer to the CryptuProEco® White Paper). |
Nickname | A nickname that you choose during the registration period. You will be known by this nickname. |
Your email should be written here. |
You should press “Submit” after completing all fields. Then you are a NEW PROMOTER in a cluster
Your Promotions
Your promotions information will be shown as Fig. 6 till Fig. 12.
Fig. 6: Your Promotions-Part 1.
The shown your promotions-part1 table consist of several columns as described in the following table:
Column Title | Description |
---|---|
Nickname | Your nickname that has been chosen during the registration period, is shown here. You will be known by this nickname. |
Referral | Your referral code that is unique. You may send it to others that they become other promoters. You can be a head of the cluster in this way and receive more commission. |
Your email which is declared during registration period. | |
Joined | The date of your registration. |
Balance | It is the current account balance. It means at the moment you can have this amount of currency. |
The other promotion data may be seen in the Fig. 7 as follows.
Fig. 7: Your Promotions-Part 2.
As it is shown in the Fig. 7, the promotion that is gained in various services, is summarized here. Each part is described as follows:
• Service:
The various service(s) that you are its (or their) promoters, is listed here as drop box.
• Total Clusters:
Here is the information of all clusters of the selected service. This table will be changed by selecting the various services.
- Count:
The number of clusters which is formed in the selected service.
- Sale:
The number of the total sales of the selected service (by the total clusters).
- Average:
The average of the total sold products of the selected service per each month.
- Income (Crypto):
Total income of the selected service in cryptocurrency.
- Income ($):
Total income of the selected service in $.
• Your Cluster:
Here is the information of each cluster, that you are its service member and you have chosen from the service drop box.
- Owner:
It is the nickname of the cluster owner.
- Promoters:
The number of promoters of the selected cluster.
- Sale:
The number of products that your cluster has traded till now in the selected service.
- Average:
The average of the sold products (in the selected service) by the promoter per each month.
- Income (Crypto):
Your cluster income in cryptocurrency for the selected service.
- Income ($):
Your cluster income in $ for the selected service.
• Your Promotions:
Here is the information of your activity in each service as follows:
- Sale:
The amount of the products that you have sold till now in the selected service.
- Average:
The average of the sold products (in the selected service) by yourself per each month.
- Income (Crypto):
Your own income in cryptocurrency for the selected service from the beginning. It may be different to the balance.
- Income ($):
Your own income in $ for the selected service from the beginning.
- Direct Commission:
It is your own commission in % from the total trading of the selected service.
- Cluster Commission:
The percentage of the commission that members of a cluster have received from the total trading.
- Total Commission:
It is the total commission that all promoters have received.
• Your Cluster's Diagram:
The cluster that you are formed, may be shown as Fig. 8.
Fig. 8: Your Promotions-Part 3.
As it is shown in Fig. 8, you can see the situation of your cluster that is formed in the selected service.
• Cluster Ranking:
The ranking of the service clusters, for the selected service, is shown in Fig. 9. It can be a criterion to find if how many percentages of clusters are in rank 1, 2, 3, 4 or 5.
Fig. 9: Your Promotions-Part 4.
• Your Cluster's History:
The history of your cluster in the selected service is shown in Fig. 10 as follows:
Fig. 10: Your Promotions-Part 5.
In this graph, history of the rank of your cluster, history of the sale count, history of the sale average and history of the number of the promoters may be seen simultaneously.
• Your History:
Here is your performance history which may be shown in Fig. 11.
Fig. 11: Your Promotions-Part 6.
In this graph you can see your own performance in your cluster of the selected service. The cluster commission (%) based on the total sale, your own direct commission (%), the number of articles that you have traded and the sale average are shown in this graph.
• Your Contact and Withdraw:
Your contact information as your Nickname and Email is shown in the Fig. 12.
Fig. 12: Your Promotions-Part 7.
Also, you can withdraw your balance as you can check it at the bottom of the Fig. 6.
Register New Service
You can register your service or business to promote your job and income. The promoters may select your service to promote it dramatically. As it is seen in Fig. 13, you need some information to complete the service registration.
Fig. 13: Register New Service.
New service registration consist of fields as described in the following table:
field Title | Description |
---|---|
Name | The name of your service is written here. |
Consumer | It is the wallet address of the service owner. The network of your wallet address should be acceptable by our side like BNB, ETH, BTC etc. |
Cluster Share | You can define the share of the cluster in ------. In other word, the cluster has its own rank that you can set it here (Refer to the CryptuProEco® White Paper). |
Level Share | Each cluster has 4 levels that each level has its own share (or its own percentage). You can write each level percentage here (Refer to the CryptuProEco® White Paper). |
Z1 (%) | Direct Commission Weight Factor in percent. |
Z2 (%) | Cluster Commission Weight Factor in percent. |
Min Discount (%) | It is the minimum discount that you (as a service owner) set here in percentage of the total selling. |
Max Discount (%) | It is the maximum discount that you (as a service owner) set here in percentage of the total selling. It is for banning your total discount from a specific number. When you set Z1 and Z2, it is probable the discount becomes very high that is not acceptable by your side. Here you set a ban that your maximum discount be under your control. |
Averaging Period (in second) | It is the number that you define the averaging period for the promoters (please refer to the item 2-3). |
Relaxation Period (in second) | The commission of the promoters is calculated based on the averaging sale (please refer to the item 2-3) that is calculated based on the averaging period. We have considered a relaxation period that the promoters’ effort will not be ruined if he/she does not sell for a period of time. In other word the averaging sale will not become low for a period of time. So, the motivation stays high for this time. |
Currency | Here is the contract address of your acceptable currency. It may be the contract address of $FARTY, BNB, BTC etc. |
Fee Payment |
You can select the commission of each promoter that you should pay, as one of the following ways:
A) 0.1 BNB B) 1% of Sale |
Defaults | You may change the values to their default via this button. |
Submit | You should finalize your registration after filling all fields. So please press the “Submit” button when you are sure that you have filled all fields. |
Your Provided Services
After the service(s) registration, you can see their situation as Fig. 14:
Fig. 14: Your Provided Services.
Your provided services consist of fields as described in the following table:
field Title | Description |
---|---|
Service | You can select one of the registered services here. |
Cluster | You can choose each cluster which are in your service(s). |
Promoter | Each promoter with their IDs is shown here. You can choose each promoter who is active in your service. |
• Service Parameters:
You may select each of your own registered service, the selective cluster ID and the selective promoter ID as shown in Fig. 15. The parameters of your registered service(s) can be changed here. In other word you can trace your service and change their parameters.
Fig. 15: Service Parameters.
Services parameters consist of fields as described in the following table:
field Title | Description |
---|---|
Consumer | It is the wallet address of the registered service owner. The network of your wallet address should be acceptable by our side like BNB, ETH, BTC etc. |
Cluster Share | You can define the share of the cluster of the registered service in ------. In other word, the cluster has its own rank that you can change it here (refer to the marketing white paper). |
Level Share | Each cluster has 4 levels that each level has its own share (or its own percentage). You can change each level percentage here (that is set in "Level Share" of the register new getServiceStatus). |
Z1 (%) | Direct Commission Weight Factor in percent. |
Z2 (%) | Cluster Commission Weight Factor in percent. |
Min Discount (%): | It is the minimum discount that you (as a service owner) can change here in percentage of the total selling. |
Max Discount (%): | It is the maximum discount that you (as a service owner) can change here in percentage of the total selling. It is for banning your total discount from a specific number. When you set Z1 and Z2, it is probable that the discount becomes very high that is not acceptable by your side. Here you change the ban that your maximum discount be under your control. |
Averaging Period (in second) | It is the number that you have defined before (Item 5-9) and you can change here (please refer to the item 2-3). |
Relaxation Period (in second) | The commission of the promoters is calculated based on the averaging sale (please refer to the item 2-3) that is calculated based on the averaging period (item 5-10). The relaxation period can be changed here so the promoters’ effort will not be ruined if he/she does not sell for a period of time. In other word the averaging sale will not become low for a period of time. |
Website | Here you can change the website of the selected service. |
Dex Router | ?????????????????? |
Submit | You can finish your work by pressing the “Submit” button. So, your change has been set. |
• Service’s history and Cluster’s History:
Here is the service and cluster history which may be shown in Fig. 16.
Fig. 16: Service's History & Cluster's History.
- Service’s History:
In this graph you can see your own service performance of the selected service. The income, the sale count, the sale average and the promoter count may be shown in the current graph.
- Cluster’s History:
In this graph, the rank of your cluster, the sale count, the sale average and the number of the promoters may be seen simultaneously.
Hint: The graphs may be changed by varying the service
• Promoter's History:
The performance of the promoters of selected service is shown in the Fig. 17.
Fig. 17: Promoter's History.
In the Fig. 17, the selective cluster commission (%) that should be paid, the specific promoter commission or direct commission (%), the sale count and the sale average of the selective service is shown.
Cryptu Lottery (CryptuLotto®) is a secure and reliable lottery platform in which gives the players the chance to raise money by buying ticket(s). If the digits on your ticket(s) match the winning numbers in correct order, you win a portion of the prize pool. There are three stages to play:
Stage 1: Buy Ticket(s)
• You may buy one ticket or more than it. Each ticket costs 2.49 USDT in $FARTY.
Stage 2: Wait for the Draw
• Since there is one draw each 24 hours, so you should wait until the final winning number is declared by the platform.
Stage 3: Check your ticket(s)
• The digits of your ticket(s) should match the winning number in the correct order, so come back to the CryptuLotto® and check to see if you`ve won!
CryptuLotto® Contract
Cryptu Lottery V1
Fork of PancakeSwap Lottery contract by using ChainLinkVRF2 V2 and Cryptu Promotion Ecosystem (CryptuProEco®).
Contract info
Contract name: CryptuLottery
Contract address: 0x5aF6D33DE2ccEC94efb1bDF8f92Bd58085432d2c
Random number generator address: 0x8c6375Aab6e5B26a30bF241EBBf29AD6e6c503c2 (Random number generator contract must be deployed first)
View CryptuLottery.sol on BscScan.
View the Cryptu.io: Lottery contract on BscScan.
Lottery Status states
The lottery has four status states as Pending, Open, Close, and Claimable, which determine the actions that can or cannot be taken at a given time.
Read/View Function
viewCurrentLotteryId
function injectFunds(uint256 _lotteryId, uint256 _amount) external override onlyOwnerOrInjector {
Returns the ID of the current Lottery round as an integer. Round IDs correlate to round number, and are incremental, e.g. the ninth round of Lottery will be 9.
viewLottery
function viewLottery(uint32 _lotteryId) external view returns (Lottery memory);
Returns information on specified Lottery round as tuple (see Lottery structure below).
struct Lottery {
Status status;
uint256 startTime;
uint256 endTime;
uint256 priceTicketInCake;
uint256 discountDivisor;
uint256 amountCollectedInCake;
uint256 treasuryFee; // 500: 5% // 200: 2% // 50: 0.5%
uint256[6] cakePerBracket;
uint64 firstTicketIdNextLottery;//gas opt
uint64 firstTicketId;//gas opt
uint32 finalNumber;
uint32 numberOfPlayers;//@dev: new feature added by Cryptu//gas opt
uint16[6] rewardsBreakdown;//gas opt // 0: 1 matching number // 5: 6 matching numbers
uint32[6] countWinningsPerBracket;//gas opt
}
Name | Type | Description |
---|---|---|
status | Status | Pending, Open, Close, Claimable. |
startTime | uint256 | Starting block for Lottery round. |
endTime | uint256 | Ending block for Lottery round (approximately 12 hours after a round begins). |
priceTicketInCake | uint256 | The price of a ticket in CAKE (approximately $2.49 USDT). |
discountDivisor | uint256 | The divisor used to calculate bulk ticket discount. |
amountCollectedInCake | uint256 | The amount of CAKE collected through ticket sales for the Lottery round. |
treasuryFee | uint256 | Amount taken from funds raised per round that's moved to treasury address (maximum 3000). |
cakePerBracket | uint256[6] | The amount of CAKE to distribute to winners of each bracket. |
firstTicketIdNextLottery | uint64 | ID of the first ticket, set at the closing of current round that determines the range of eligible tickets for the current round. |
firstTicketId | uint64 | ID of the first ticket, set with the opening of the Lottery round that determines the range of eligible tickets for the current round. |
FinalNumber | uint32 | The winning ticket number of this round in reverse order. |
numberOfPlayers | uint32 | Number of wallets, which purchased ticket in this round. |
rewardsBreakdown | uint16[6] | The division of rewards across brackets (total must add up to 10,000). |
countWinnersPerBracket | uint32[6] | Moves through brackets, starting from the highest, accounting for winners when value > 0. |
viewNumbersAndStatusesForTicketIds
function viewNumbersAndStatusesForTicketIds(uint64[] calldata _ticketIds)
external
view
returns (uint32[] memory, bool[] memory)
Returns the corresponding numbers and the statuses of ticketIds array of tickets defined by their ticketId.
viewRewardsForTicketId
function viewRewardsForTicketId(
uint32 _lotteryId,
uint32 _ticketId,
uint32 _bracket
) external view returns (uint256)
Calculates rewards for a ticket after draw given the lotteryId, ticketId, and bracket. Filling and querying will provide a link to detailed price information on BscScan.
Name | Type | Description |
---|---|---|
lotteryId | uint32 | The ID of the Lottery. |
ticketId | uint32 | The ID of the ticket. |
bracket | uint32 | Bracket for the ticketId to verify the claim and calculate rewards. |
viewUserInfoForLotteryId
function viewUserInfoForLotteryId(
address _user,
uint32 _lotteryId,
uint32 _cursor,
uint32 _size
)
external
view
returns (
uint64[] memory,
uint32[] memory,
bool[] memory,
uint256
)
Returns user lotteryTicketIds, ticketNumbers, ticketStatuses and current data cursor of a user for a given Lottery (defined by lotteryId).
Name | Type | Description |
---|---|---|
User | address | The address of the user. |
lotteryId | uint32 | The ID of the Lottery. |
cursor | uint32 | Cursor to start where to retrieve the tickets. |
size | uint32 | The number of tickets to retrieve. |
viewRewardsForTicketId
function viewRewardsForTicketId(
uint32 _lotteryId,
uint32 _ticketId,
uint32 _bracket
) external view returns (uint256)
Calculates rewards for a ticket after draw given the lotteryId, ticketId, and bracket.
Name | Type | Description |
---|---|---|
lotteryId | uint32 | The ID of the Lottery. |
ticketId | uint32 | The ID of the ticket. |
bracket | uint32 | Bracket for the ticketId to verify the claim and calculate rewards. |
calculateTotalPriceForBulkTickets
function calculateTotalPriceForBulkTickets(
uint256 _discountDivisor,
uint256 _priceTicket,
uint256 _numberTickets,
bytes10 _refCode
) external view returns (uint256)
Calculates the price for a set of tickets accounting for bulk and referral code (Cryptu.io added this new feature) discount.
discountDivisor:
totalPriceForBulkTickets = priceSingleTicket * numberTickets * (discountDivisor +1 - numberTicket) / discountDivisor
Filling and querying will provide a link to detailed price information on BscScan.
Name | Type | Description |
---|---|---|
discountDivisor | uint256 | The divisor for the discount. |
priceTickets | uint256 | The price of a ticket in CAKE. |
numberTickets | uint256 | The number of tickets to buy. |
refCode | bytes10 | 10 bytes, zero padded referral code from Cryptu Promotion Manager Ecosystem. Must be 0 if no referral code is supplied. |
viewUserWinningTickets (Cryptu.io added this new feature)
function viewUserWinningTickets(address _user,uint32 _lotteryId) external view returns(uint256 , WinningTicket[] memory )
Returns array of WinnigTicket structures for the user in the Lottery that its lotteryId is supplied in.
Name | Type | Description |
---|---|---|
user | address | The address of the user. |
lotteryId | uint32 | The ID of the Lottery. |
struct WinningTicket{//gas opt
bool claimed;
uint8 bracket;
uint32 number;
uint64 id;
uint256 prize;
}
Name | Type | Description |
---|---|---|
claimed | bool | Whether the ticket is claimed or not. |
bracket | uint8 | The bracket that this ticket is winning in it. |
number | uint32 | Ticket number. |
id | uint64 | The Lottery ID. |
prize | uint256 | The amount of Cake token that this ticket is won.. |
ViewUserLotteries (Cryptu.io added this new feature)
function viewUserLotteries(address _user) external view returns(uint32 [] memory)
Returns array of lottery ids that this user is participated in.
Write Functions (User)
buyTickets
function buyTickets(uint32 _lotteryId, uint32[] calldata _ticketNumbers,bytes10 _refCode/*Promotion Manager Support*/) external override notContract nonReentrant
Buy tickets for the current Open Lottery round (between 1 and 100 per purchase). Calculates the price per ticket using calculateTotalPriceForBulkTickets.
Name | Type | Description |
---|---|---|
lotteryId | uint32 | The id of the lottery. |
ticketNumbers | uint32[] | Array of ticket numbers between 1,000,000 and 1,999,999. |
refCode | bytes10 | 10 bytes, zero padded referral code from Cryptu Promotion Manager Ecosystem. Must be 0 if no referral code is supplied. |
claimTickets
function claimTickets(uint32 _lotteryId,uint64[] calldata _ticketIds, uint32[] calldata _brackets) external override notContract nonReentrant
Claim a set of winning tickets for a claimable lottery round. Checks lotteryId to determine if round is claimable, ownership of ticketId, eligibility of ticket (ticketId falls between firstTicketId and firstTicketIdNextLottery), and whether ticketId falls within eligible prize bracket (between 0 and 5).
Name | Type | Description |
---|---|---|
lotteryId | uint32 | The ID of the lottery. |
ticketIds | uint64[] | Array of ticketIds. |
brackets | uint32[] | Array of brackets for the ticket ids. |
Write Functions (Operator/Admin)
closeLottery
function closeLottery(uint32 _lotteryId) external override onlyOperator nonReentrant
Closes the open lottery to close state. Emits LotteryClose event.
Name | Type | Description |
---|---|---|
lotteryId | uint32 | The ID of the lottery. |
drawFinalNumberAndMakeLotteryClaimable
function drawFinalNumberAndMakeLotteryClaimable(uint32 _lotteryId, bool _autoInjection) external override onlyOperator nonReentrant
Lottery must be in close state. Draws the final Lottery number for results from randomResult, calculates the rewards for brackets after accounting for treasury fee, makes Lottery state Claimable, and transfers treasury fee to treasury address.
Name | Type | Description |
---|---|---|
lotteryId | uint32 | The ID of the lottery. |
autoInjection | boll | Automatic injection status. |
changeRandomGenerator
function changeRandomGenerator(address _randomGeneratorAddress) external OnlyOwner
Changes the random number generator contract address. Lottery must be Claimable.
Name | Type | Description |
---|---|---|
randomGeneratorAddress | address | The random generator address.. |
injectFunds
function injectFunds(uint32 _lotteryId, uint256 _amount) external override onlyOwnerOrInjector
Inject funds into a Lottery. Lottery must be Open.
Name | Type | Description |
---|---|---|
lotteryId | uint32 | The id of the lottery. |
amount | unit256 | Amount, in CAKE token, to inject. |
startLottery
function startLottery(
uint256 _endTime,
uint256 _priceTicketInCake,
uint256 _discountDivisor,
uint16[6] calldata _rewardsBreakdown,
uint256 _treasuryFee
) external override onlyOperator
Starts the Lottery, setting it to Open state. Status must be Claimable.
Name | Type | Description |
---|---|---|
endTime | uint256 | End time of the Lottery. |
priceTicketInCake | unit256 | Price of a ticket in CAKE. |
discountDivisor | uint256 | The divisor to calculate the discount magnitude for bulks. |
rewardsBreakdown | uint16[6] | Breakdown of rewards per bracket (must sum to 10,000). |
trasuryFee | uint256 | Treasury fee (10,000 = 100%, 100 = 1%). |
recoverWrongTokens
function recoverWrongTokens(address _tokenAddress, uint256 _tokenAmount) external onlyOwner
Allows admin to recover incorrect tokens sent to address mistakenly. Cannot be CAKE tokens.
Name | Type | Description |
---|---|---|
tokenAddress | address | The address of the token to withdraw. |
tokenAmount | unit256 | The number of tokens to withdraw. |
setMinAndMaxTicketPriceInCake
function setMinAndMaxTicketPriceInCake(uint256 _minPriceTicketInCake, uint256 _maxPriceTicketInCake) external onlyOwner
Allows admin to set upper and lower limit of ticket price in CAKE value. Minimum price must be lower than maximum price.
Name | Type | Description |
---|---|---|
minPriceTicketInCake | uint256 | The minimum price in CAKE. |
maxPriceTicketInCake | unit256 | The maximum price in CAKE. |
setMaxNumberTicketsPerBuy
function setMaxNumberTicketsPerBuy(uint256 _maxNumberTicketsPerBuy) external onlyOwner
Set max number of tickets purchasable at a time (presently 100). Max number of tickets must be higher than 0.
Name | Type | Description |
---|---|---|
maxNumberTicketsPerBuy | uint256 | Max number of tickets in one purchase. |
setOperatorAndTreasuryAndInjectorAddress
function setOperatorAndTreasuryAndInjectorAddresses(
address _operatorAddress,
address _treasuryAddress,
address _injectorAddress
) external onlyOwner
Sets the address of the Lottery operator.
Name | Type | Description |
---|---|---|
operatorAddress | address | The address of the operator. |
treasuryAddress | address | The address of the treasury. |
injectorAddress | address | The address of the injector. |
Events (User)
TicketsPurchase
event TicketsPurchase(address indexed buyer, uint32 indexed lotteryId, uint32 numberTickets);
Lottery tickets are purchased.
Emitter: buyTickets go to buyTickets.
TicketsClaim
event TicketsClaim(address indexed claimer, uint256 amount, uint32 indexed lotteryId, uint32 numberTickets);
Lottery tickets are claimed post-draw.
Emitter: claimTickets go to claimTickets.
OnCommisionTransfered
event OnCommisionTransfered(uint256 amount,bytes10 refCode);//optional event that shows the commission transfer
Optional event for commission transfer to the Cryptu Promotion Manager contract, can be emitted in buyTicket function.
Events (Admin)
AdminTokenRecovery
event AdminTokenRecovery(address token, uint256 amount);
Admin recovers incorrect tokens from Lottery address.
Emitter: recoverWrongTokens go to recoverWrongTokens.
LotteryClose
event LotteryClose(uint32 indexed lotteryId, uint64 firstTicketIdNextLottery);
The Lottery is closed. lotteryId is indexed and firstTicketIdNextLottery is determined by currentTicketId.
Emitter: closeLottery go to closeLottery.
LotteryInjection
event LotteryInjection(uint32 indexed lotteryId, uint256 injectedAmount);
Funds are injected into Lottery.
Emitter: injectFunds go to injectFunds.
LotteryOpen
event LotteryOpen(uint32 indexed lotteryId,uint256 startTime,
uint256 endTime,uint256 priceTicketInCake,
uint64 firstTicketId,uint256 injectedAmount);
The Lottery is opened. firstTicketId is set from currentTicketId,
Emitter: startLottery go to startLottery.
LotteryNumberDrawn
event LotteryNumberDrawn(uint32 indexed lotteryId, uint32 finalNumber, uint32 countWinningTickets);
Lottery numbers are drawn for Lottery round.
Emitter: drawFinalNumberAndMakeLotteryClaimable go to drawFinalNumberAndMakeLotteryClaimable.
NewOperatorAndTreasuryAndInjectorAddresses
event NewOperatorAndTreasuryAndInjectorAddresses(address operator, address treasury, address injector);
New operator address is set.
Emitter: setOperatorAndTreasuryAndInjectorAddresses go to setOperatorAndTreasuryAndInjectorAddresses.
NewRandomGenerator
event NewRandomGenerator(address indexed randomGenerator);
New random number generator address is set.
Emitter: changeRandomGenerator go to changeRandomGenerator.
Contract Roles
Role | Description |
---|---|
injectorAddress (onlyInjector) | Injector is the address used to fund the lottery with periodic injections. |
operatorAddress (onlyOperator) | The lottery scheduler account used to run regular operations. |
treasuryAddress (onlyTreasury) | The address in which the burn is sent |
Owner (onlyOwner) | The contract owner |
Role Description
Owner
0xad9d97fc7bf0ac6dc68d478dcb3709454519b358
Address controlled by gnosis multisignature contract with a threshold of 3/6
Operator Address
0x566a7e38b300E903dE71389C2b801AcDBA5268dB
Scheduler address - entirely automated and no human interaction. Not on multisig and doesn't have access to sensitive contract operations.
Treasury Address
0xe2086f890e7bd20e07fc0036a437dc4813e88b09
Address controlled by gnosis multisignature contract with a threshold of 3/6
0xaD9d97fc7BF0ac6dC68d478dcB3709454519b358
Address controlled by gnosis multisignature contract with a threshold of 3/6
Functions
injectFunds - Injector and Owner
function injectFunds(uint32 _lotteryId, uint256 _amount) external override
onlyOwnerOrInjector {
require(_lotteries[_lotteryId].status == Status.Open, "Lottery not open");
cakeToken.safeTransferFrom(address(msg.sender), address(this), _amount);
_lotteries[_lotteryId].amountCollectedInCake += _amount;
emit LotteryInjection(_lotteryId, _amount);
}
The Injector or Owner can call this function to inject a specific lotteryId with a specified amount of CAKE.
startLottery - Operator
function startLottery(
uint256 _endTime,
uint256 _priceTicketInCake,
uint256 _discountDivisor,
uint16[6] calldata _rewardsBreakdown,
uint256 _treasuryFee
) external override onlyOperator {
require(
(currentLotteryId == 0) || (_lotteries[currentLotteryId].status == Status.Claimable),
"Not time to start lottery"
);
require(
((_endTime - block.timestamp) > MIN_LENGTH_LOTTERY) && ((_endTime - block.timestamp) < MAX_LENGTH_LOTTERY),
"Lottery length outside of range" );
require(
(_priceTicketInCake >= minPriceTicketInCake) && (_priceTicketInCake <= maxPriceTicketInCake),
"Outside of limits"
);
require(_discountDivisor >= MIN_DISCOUNT_DIVISOR, "Discount divisor too low");
require(_treasuryFee <= MAX_TREASURY_FEE, "Treasury fee too high");
require(
(_rewardsBreakdown[0] +
_rewardsBreakdown[1] +
_rewardsBreakdown[2] +
_rewardsBreakdown[3] +
_rewardsBreakdown[4] +
_rewardsBreakdown[5]) == 10000,
"Rewards must equal 10000"
);
currentLotteryId= _lowgas_inc_32(currentLotteryId);//gas opt /
_lotteries[currentLotteryId] = Lottery({
status: Status.Open,
startTime: block.timestamp,
endTime: _endTime,
priceTicketInCake: _priceTicketInCake,
discountDivisor: _discountDivisor,
rewardsBreakdown: _rewardsBreakdown,
treasuryFee: _treasuryFee,
cakePerBracket: [uint256(0), uint256(0), uint256(0), uint256(0), uint256(0), uint256(0)],
countWinningsPerBracket: [uint32(0), uint32(0), uint32(0), uint32(0), uint32(0), uint32(0)],
firstTicketId: currentTicketId,
firstTicketIdNextLottery: currentTicketId,
amountCollectedInCake: pendingInjectionNextLottery,
finalNumber: 0,
numberOfPlayers:0
});
emit LotteryOpen(
currentLotteryId,
block.timestamp,
_endTime,
_priceTicketInCake,
currentTicketId,
pendingInjectionNextLottery
);
pendingInjectionNextLottery = 0;
}
The startLottery function is only callable by the Operator in order to start a new lottery round.
closeLottery - Operator
function closeLottery(uint32 _lotteryId) external override onlyOperator nonReentrant {
require(_lotteries[_lotteryId].status == Status.Open, "Lottery not open");
require(block.timestamp > _lotteries[_lotteryId].endTime, "Lottery not over");
require(block.timestamp > _lotteries[_lotteryId].endTime,uint2str(block.timestamp) );
_lotteries[_lotteryId].firstTicketIdNextLottery = currentTicketId;
//*************************************************************
//new call using ChainLink VRF2
randomGenerator.getRandomNumber();
//*************************************************************
_lotteries[_lotteryId].status = Status.Close;
emit LotteryClose(_lotteryId, currentTicketId);
}
Callable by the Operator to close a round of the lottery.
drawFinalNumberAndMakeLotteryClaimable - Operator
function drawFinalNumberAndMakeLotteryClaimable(uint32 _lotteryId, bool _autoInjection)
external
override
onlyOperator
nonReentrant
{
// Calculate the finalNumber based on the randomResult generated by ChainLink's fallback
uint32 finalNumber = randomGenerator.viewRandomResult();
//******************************************************************************************
//@dev: preventing number duplication due to lack of Link balance of random generator
if(currentLotteryId!=0)
{
if(_lotteries[currentLotteryId-1].finalNumber==finalNumber)//previous round number
revert("Wrong final number!");
}
//*******************************************************************************************
// Initialize a number to count addresses in the previous bracket
uint32 numberAddressesInPreviousBracket;
_lotteryId=_lotteryId;
_autoInjection=true;
// Calculate the amount to share post-treasury fee
uint256 amountToShareToWinnings = (
((_lotteries[_lotteryId].amountCollectedInCake) * (10000 - _lotteries[_lotteryId].treasuryFee))
) / 10000;
// Initializes the amount to withdraw to treasury
uint256 amountToWithdrawToTreasury;
// Calculate prizes in CAKE for each bracket by starting from the highest one
for (uint32 i; i < 6;) {
uint32 j = 5 - i;
uint32 transformedWinningNumber = _bracketCalculator[j] + (finalNumber % (uint32(10)**(j + 1)));
_lotteries[_lotteryId].countWinningsPerBracket[j] =
_numberTicketsPerLotteryId[_lotteryId][transformedWinningNumber] -
numberAddressesInPreviousBracket;
// A. If number of users for this _bracket number is superior to 0
if (
(_numberTicketsPerLotteryId[_lotteryId][transformedWinningNumber] - numberAddressesInPreviousBracket) !=
0
) {
// B. If rewards at this bracket are > 0, calculate, else, report the numberAddresses from previous bracket
if (_lotteries[_lotteryId].rewardsBreakdown[j] != 0) {
_lotteries[_lotteryId].cakePerBracket[j] =
((_lotteries[_lotteryId].rewardsBreakdown[j] * amountToShareToWinnings) /
(_numberTicketsPerLotteryId[_lotteryId][transformedWinningNumber] -
numberAddressesInPreviousBracket)) /
10000;
// Update numberAddressesInPreviousBracket
numberAddressesInPreviousBracket = _numberTicketsPerLotteryId[_lotteryId][transformedWinningNumber];
}
// A. No CAKE to distribute, they are added to the amount to withdraw to treasury address
} else {
_lotteries[_lotteryId].cakePerBracket[j] = 0;
amountToWithdrawToTreasury +=
(_lotteries[_lotteryId].rewardsBreakdown[j] * amountToShareToWinnings) /
10000;
}
unchecked{++i;}//gas opt
}
// Update internal statuses for lottery
_lotteries[_lotteryId].finalNumber = finalNumber;
_lotteries[_lotteryId].status = Status.Claimable;
if (_autoInjection) {
pendingInjectionNextLottery = amountToWithdrawToTreasury;
amountToWithdrawToTreasury = 0;
}
amountToWithdrawToTreasury += (_lotteries[_lotteryId].amountCollectedInCake - amountToShareToWinnings);
// Transfer CAKE to treasury address
if(amountToWithdrawToTreasury!=0)//@dev
cakeToken.safeTransfer(treasuryAddress, amountToWithdrawToTreasury);
emit LotteryNumberDrawn(currentLotteryId, finalNumber, numberAddressesInPreviousBracket);
}
For Operator to draw the final number using ChainLink VRF2 function.
recoverWrongTokens - Owner
function recoverWrongTokens(address _tokenAddress, uint256 _tokenAmount)
external onlyOwner {
require(_tokenAddress != address(cakeToken), "Cannot be CAKE token");
IERC20(_tokenAddress).safeTransfer(address(msg.sender), _tokenAmount);
emit AdminTokenRecovery(_tokenAddress, _tokenAmount);
}
In the case of tokens other than CAKE mistakenly being sent to the lottery contract, this function is used to recover them and is only callable by the Owner.
setMinAndMaxTicketPriceInCake - Owner
function setMinAndMaxTicketPriceInCake(uint256 _minPriceTicketInCake, uint256 _maxPriceTicketInCake)
external
onlyOwner
{
require(_minPriceTicketInCake <= _maxPriceTicketInCake, "minPrice must be < maxPrice");
minPriceTicketInCake = _minPriceTicketInCake;
maxPriceTicketInCake = _maxPriceTicketInCake;
}
To prevent the Operator setting the tickets to arbitrary prices during the event of a flash crash/pump.
setMaxNumberTicketsPerBuy - Owner
function setMaxNumberTicketsPerBuy(uint256 _maxNumberTicketsPerBuy) external onlyOwner {
require(_maxNumberTicketsPerBuy != 0, "Must be > 0");
maxNumberTicketsPerBuyOrClaim = _maxNumberTicketsPerBuy;
}
The Owner can modify the maximum number of tickets per transaction. This may be modified in the case of BSC block size increasing or decreasing.
setOperatorAndTreasuryAndInjectorAddresses - Owner
function setOperatorAndTreasuryAndInjectorAddresses(
address _operatorAddress,
address _treasuryAddress,
address _injectorAddress
) external onlyOwner {
require(_operatorAddress != address(0), "Cannot be zero address");
require(_treasuryAddress != address(0), "Cannot be zero address");
require(_injectorAddress != address(0), "Cannot be zero address");
operatorAddress = _operatorAddress;
treasuryAddress = _treasuryAddress;
injectorAddress = _injectorAddress;
emit NewOperatorAndTreasuryAndInjectorAddresses(_operatorAddress, _treasuryAddress, _injectorAddress);
}
Function used to set the Operator, Treasury, and Injector addresses.
changeRandomGenerator
function changeRandomGenerator(address _randomGeneratorAddress) external onlyOwner {
require(_lotteries[currentLotteryId].status == Status.Claimable, "Lottery not in claimable");
//********************************************************************
//@dev: using ChainLink VRF V2
IRandomNumberGenerator(_randomGeneratorAddress).getRandomNumber();
//********************************************************************
// Calculate the finalNumber based on the randomResult generated by ChainLink's fallback
IRandomNumberGenerator(_randomGeneratorAddress).viewRandomResult();
randomGenerator = IRandomNumberGenerator(_randomGeneratorAddress);
emit NewRandomGenerator(_randomGeneratorAddress);
}
For the Owner to update the RandomNumberGenerator contract in case we need to update the drawing logic, or release an update.
Cryptu Mint Token (CryptuMint®) is a professional platform that you can mint and generate your own tokens and record the information on to the specific blockchain without approving any banks or financial institutions and without any coding. In other word your own tokens are generated in decentralized method and in a few simple steps without the need for coding. There are two plans available on CryptuMint® for minting over 7 well-known crypto networks as follows:
• This plan is free of charge but in this choice, the token name and symbol cannot be searched in any blockchain networks and the probability of choosing a duplicate token name in this plan is very high.
• This plan costs 10 USD that you can pay in ETH, USDT, BNB, FARTY, WBNB, MATIC, AVAX, DODGE and FTM by connecting your wallet. The token name and symbol can be searched by our engine in the selected blockchain networks to find any occurrence of your token's name in order to choose a unique name.
The well-known crypto networks are as Arbitrum One, Avalanche, BSC, Doge Chain, Ethereum, Fantom Opera and Polygone.
CryptuMint® Free Plan is a professional platform under Cryptu.io that you can mint and generate your own tokens without approving any banks or financial institutions and without any coding.
Advantages:
• Totaly free of charge for minting token, except transaction fee for blockchain network.
• Create your crypto currency token without approving any banks or financial institutions and your own tokens are generated in decentralized method.
• Create your crypto currency token without any coding and in a few simple steps.
• Minting your crypto currency token over 7 well-known crypto networks are as Arbitrum One, Avalanche, BSC, Doge Chain, Ethereum, Fantom Opera and Polygone.
• ERC20 token types are available now.
• Get the TBC®, a free, unique and without any other example certificate in the crypto world for token which you have minted by CryptuMint® to show others the real date of your token’s birth and for the porpuse of anti scamming.
Disadvantages:
• The token name and symbol cannot be searched in any blockchain networks.
• The probability of choosing a duplicate token name in this plan is very high.
CryptuMint® Premium Plan is a professional platform under Cryptu.io that you can mint and generate your own tokens without approving any banks or financial institutions and without any coding.
Advantages:
• Totaly free of charge for minting token, except transaction fee for blockchain network and the TUC® cost.
• Only 10 USD cost to check the uniqueness of the token name and issue the TUC® that you can pay in ETH, USDT, BNB, FARTY, WBNB, MATIC, AVAX, DODGE and FTM by connecting your wallet.
• Powerfull and advanced search engine developed by Cryptu.io to check the token name and symbol in the selected blockchain networks to find any occurance of your token's name in order to choose a unique name.
• Create your crypto currency token without approving any banks or financial institutions and your own tokens are generated in decentralized method.
• Create your crypto currency token without any coding and in a few simple steps.
• Minting your crypto currency token over 7 well-known crypto networks are as Arbitrum One, Avalanche, BSC, Doge Chain, Ethereum, Fantom Opera and Polygone.
• ERC20 token types are available now.
• Get the TBC®, a free, unique and without any other example certificate in the crypto world for token which you have minted by CryptuMint® to show others the real date of your token’s birth and for the porpuse of anti scamming.
• Get the TUC®, a unique and without any other example certificate in the crypto world for token which you have minted by CryptuMint® or minted by third parties to show that your token name is unique in the selected blockchain networks till the date certified on the purchased TUC® for the porpuse of anti scamming.
Cryptu Token Query (CryptuQuery®) is a comprehensive platform of our website in which the validity of certificates, that has been generated by Cryptu.io, can be checked. The QR code of TBC®/TUC® or token contract address may be checked in CryptuQuery® then system will show you if the certificates are ok or not.
TOKEN BIRTH CERTIFICATE® (TBC®) is a free of charge certificate and it is without any other example in the crypto world in which you can show others the real date of your token’s birth which you have minted in CryptuMint® and you will recieve it from our side. In other word if another token is minted by your token name (after your token birth), you will prove by TBC® that your token is the first. Also, all TBCs will be equipped by a QR code that all people can search the validation of certificate in our comprehensive platform called CryptuQuery®.
TOKEN UNITY CERTIFICATE® (TUC®) is a premium and paid certificate and it is without any other example in the crypto world that you may purchase it to show that your token name is unique in the selected blockchain networks. Our professional platform has the ability to search in several networks depends on your selection by powerfull and advanced search engine developed by Cryptu.io team. The price for TUC® is calculated by the networks selection and you can pay it in ETH, USDT, BNB, FARTY, WBNB, MATIC, AVAX, DODGE and FTM by connecting your wallet before achieving the certificate. In other word, if you mint by CryptuMint®, so you will have free of charge TBC® and you may purchase TUC®. Else if you have minted by others, so you can purchase your own TUC®. Also all TUCs equipped by a QR code that all people can search the validation of certificate in our comprehensive platform called CryptuQuery®.
$FARTY is the first meme coin ever exists to engage with a social-political real world's problem.
Since the day in which Satoshi invented the first crypto currency, the Bitcoin, several thousands of crypto currencies have been created. In 2013 Billy Markus and Jackson Palmer made the first joke coin (meme coin) the Doge, making fun only, but today the coin has a market capacity over 48 billion US dollars! According to the great victory of Doge, many meme coins have been developed over the net, such as Shiba Inu that is another successful meme token project.
But no meme coin ever exists to engage with a social-political real world's problem, all of them are just jokes!
In December of 2021, Tatashi Toushe founded the first meme token project that focuses on the problem of sleepy presidents. She named the token "Old Fart" after the US President Joe Biden farting at the COP26 climate talks in November 2021 to recall and bold the sleepy presidents' problem as a joke. So for more information about the $FARTY, please visit the OldFart Subdomain.
In December of 2021, Tatashi Toushe founded the first meme token project that focuses on the social-political real world's problem. She named the token "Old Fart" and also created a new type of white paper, the "Fart Paper"! Just like the dog type meme coins Woof Paper! So for more information about the project, please read the Fart Paper!