
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 cryptocurrency, 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.
Cryptu Promotion Ecosystem (CryptuProEco®) is an unique, professional and comprehensive cryptocurrency-based promotion management ecosystem under Cryptu.io without any other example in the crypto world that you may enter it to increase your revenue. In other word for 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.
The CryptuProEco® consists of two sections, Promoters and Providers. In other word if you have your own business, and you want to promote your business, you may register a new Service as a Provider else you may would like to register as a new Promoter on a previously registered Service by a Provider to take benefit of your promotions.
Promoter
A person with a wallet address that wants to be a Promoter in CryptuProEco® and try to reach investors. 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 Promoter(s). He/she/it creates a Service on the CryptuProEco® to starts his/her/its promotion ecosystem.
Service
In a word, a Service is a business. The owner of a company or a person (Provider) may like to extend his/her/its business. You can register your goods/services/business as a Service on the CryptuProEco® and Promoter(s) can promote/advertise and sell your articles, helping your business to be developed more. They can help you to absorb the customers, so your revenue will increase. Also, the Promoter(s) get a commission of your sale according their activity.
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 Ecosystem (CryptuProEco®) emphasizes 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 (CryptuPromotionManager V1)
Smart contract implementation of Cryptu Promotion Ecosystem (CryptuProEco®).
Contract info
Contract name: CryptuPromotionManager
Contract address: 0x5aF6D33DE2ccEC94efb1bDF8f92Bd58085432d2c
View CryptuPromotionManager.sol on BscScan.
View the CryptuProEco® White Paper for more information.
CryptuProEco® Structure
The CryptuProEco®, which is invented by Cruptu.io is a novel cryptocurrency-based promotion management ecosystem, 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. CryptuProEco® structure is shown in Fig. 1.
Fig. 1: CryptuProEco® 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 CryptuProEco®. The Promoter level is the lowest (4) now. If he/she gives his/her 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 CryptuProEco® 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 CryptuProEco® 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 Commission and Cluster Commission 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 CryptuProEco®'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 CryptuPromotionManager 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 CryptuProEco® otherwise it reverts. |
Consumer | address | Address of the Consumer contract, which will use the CryptuProEco®. Consumer contract must be a verified contract, so the CryptuProEco®'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! |
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 CryptuProEco®. Consumer contract must be a verified contract, so the CryptuProEco®'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! |
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 CryptuProEco®, that a successful buy operation is finished. It emits OnCodeUsed event.
The Consumer contract, must report refCode used, buy count of goods/services, transferred commission amount of the Promoter, transferred fee amount of the CryptuProEco® (if sale percent is selected at Service registration time). Before calling this function, Consumer contract must transfer Promoter's commission amount and CryptuProEco®'s fee (if sale percent is selected at Service registration time), to the CryptuPromotionManager contract.
Consumer contract must be a verified contract, so the CryptuProEco®'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 CryptuPromotionManager 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/services. |
commissionAmount | uint256 | Transferred amount of Promoter's commission. |
fee | uint256 | Transferred amount of CryptuProEco® 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 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 CryptuPromotionManager 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 CryptuPromotionManager 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 CryptuProEco®’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!
In this instruction, you can learn how the CryptuProEco® works and how to use it.
The CryptuProEco® webpage consists of three main sections, Tops, Promoters and Providers. In other word if you have your own business, and you want to promote your business, you may register a new Service as a Provider else you may would like to register as a new Promoter on a previously registered Service by a Provider to take benefit of your promotions.
The first step is to connect your wallet (Fig. 1). Our registration is free of charge for the Promoter(s).
Fig. 1: Connecting Wallet.
You may see a column in the left-hand side of the CryptoProEco® webpage contains three main sections. The first item is “Tops“, the second is “Promoters“ and the third one is “Providers“ (Fig. 2).
Fig. 2: Main Sections.
The “Tops“ has two sub-items (lists):
• Top Services (Providers)
• Top Promoters
Top Services
The top Services may be seen in Fig. 3. This list shows the top businesses which are registered in the CryptuProEco® and they are sorted based on their sale counts.
Fig. 3: Top Services.
The shown top Services list consist of several columns as described in the following table:
Column Title | Description |
---|---|
Name | The name (or title) of the Service. |
Rank | The rank of the desired Service may be shown in the rank place based on total sale count. |
Sale Count | The amount of the companies’ articles that are traded on CryptuProEco®. |
Total Income ($) | The revenue of all Promoters of the top Services in US Dollar (if the crypto-currency price is retrievable) till now. |
Total Income (Crypto) | The revenue of all Promoters of the top Services in cryptocurrency, by the currency in which the Service uses. The currency is set during the Service registration (refer sec. 5-11). |
Promoters Count | Number of the Promoters that are registered in the desired top Services. |
Currency | The acceptable currency of the desired top Services (token/native cryptocurrency). |
Website | The website of the Service. |
Top Promoters
In this section, the top Promoters of the total ecosystems is shown as Fig. 4. The list shows the top Promoters’ situation based on their sale averages in the CryptuProEco®
Fig. 4: Top Promoters.
The shown top promoters list consist of several columns as described in the following table:
Column Title | Description |
---|---|
Nickname | This is the title that each Promoter has chosen for him/herself during registration. |
Level | The level of each Promoter is specified by his/her activity (refer to the CryptuProEco® Contract). |
Sale Average | The average of the sold articles by the Promoter per time, for example this average can be daily or any time slice in the order of seconds, specified by the related Service Provider. |
Sale Count | The amount of the articles that is sold by each Promoter. |
Income ($) | The income of each Promoter in US Dollar (if the cryptocurrency price is retrievable). |
Income (Crypto) | The income of each Promoter in cryptocurrency. |
Commission (%) | Total percentage of earned by the Promoter. |
The “Promoters“ has two sub-items:
• Register New Promoter
• Your Promotions
Register New Promoter
A Promoter can register him/herself using a wallet (just MetaMask is supported now) that must be connected to the CryptuProEco®.
There are two ways to register as Promoter:
• Registration with a Referral Code; In this way, you may have a Referral Code of another Promoter and you want to be registered as his/her sub-Promoter.
• Registration without a Referral Code; In this option, you don't have any Referral Code, so you would create your own Cluster in the selected Service.
Each Promoter should have been registered and their information must enter in the "Register New Promoter" 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 desired Service is selected here. If you don’t have a Referral Code, obtained from other Promoters, you have to choose a Service, so you would create a new Cluster in the selected Service and you become its owner, else and if other Promoter has introduced a Service, so you will have a Referral Code, so you have to select “By Referral Code” and enter it in the ”Referral” field. So, you will become the sub-Promoter of that Promoter, whom you entered his/her Referral Code automatically. (refer to the CryptuProEco® Contract). |
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® Contract). |
Nickname | A unique nickname in a Service, that you choose for yourself in the selected Service. You will be known by this nickname. |
Your email should be written here. It is better to fill it in order to be used by other Promoters of the Cluster to make contact by each others. |
You should click “Submit” after completing all fields. Then you are A NEW PROMOTER in a Cluster (refer to the CryptuProEco® Contract).
Your Promotions
Your promotions information can be shown in the “Your Promotions” section as Fig. 6 till Fig. 12.
Fig. 6: Your Promotions-Part 1.
The shown your promotions-part1 list consist of several columns as described in the following table:
Column Title | Description |
---|---|
Nickname | Your nickname that has been chosen at registration time, is shown here. |
Referral | Your Referral Code that is unique over the entire CryptuProEco®. You may give it to other Promoters that they can become your sub-Promoters or to a Buyer, whom may use it to buy articles with discount. (Refer to the CryptuProEco® Contract) |
Your registered email address. | |
Joined | The date of your registration. |
Balance | It is the current income balance. If some articles are sold using your Referral Code, you will see commission balance here. |
Service | The Service(s) that you are registered in as Promoter. By selecting a Service, you can see your promotion activity and information. |
Withdraw | You can withdraw your balance by pressing this button. |
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:
• Total Clusters:
Here is the information of all Clusters of the selected Service. This list is changed by selecting the various Services.
- Count:
Number of Clusters which is formed in the selected Service.
- Sale:
Number of the total sales of the selected Service (by the total Clusters).
- Average:
Sale average of the total sold articles of the selected Service per time, for example this average can be daily or any time slice in the order of seconds, specified by the Service Provider
- Income (Crypto):
Total income of the selected Service in cryptocurrency. In this example, it is TFARTY.
- Income ($):
Total income of the selected Service in US Dollar (if retrievable).
- Sale Share Chart:
Your sale compare to total Clusters of the Service, ratio in percent.
• Your Cluster:
Here is the information of the Cluster that you are registered in as a Promoter.
- Owner:
It is the nickname of your Cluster owner.
- Promoters:
Number of Promoters of your Cluster (refer to the CryptuProEco® Contract)
- Sale:
Number of products that your Cluster has sold till now.
- Average:
Sale average of the sold articles (in the selected Service) by the all Promoters of your Cluster per time, for example this average can be daily or any time slice in the order of seconds.
- Income (Crypto):
Your Cluster total income in cryptocurrency for the selected Service. In this example, it is TFARTY.
- Income ($):
Your Cluster income in US Dollar.
- Sale Share Chart:
Your sale compare to other Promoters of the Cluster, ratio in percent.
• Your Promotions:
Here is the information of your promotion activity in the selected service as follows:
- Sale:
Amount of the articles that are sold using your Referral Code.
- Average:
Sale average of the articles that are sold using your Referral Code over time.
- Income (Crypto):
Your own total income in cryptocurrency from the beginning. In this example, it is TFARTY.
- Income ($):
Your own income in US Dollar from the beginning.
- Direct Commission:
The percentage of your sale Direct Commission.
- Cluster Commission:
The percentage of your sale Cluster Commission.
- Total Commission:
It is the Total Commission, sum of direct and cluster commissions.
• Your Cluster's Diagram:
The Cluster structure that you are registered in. You can see all of Promoters in your Cluster of the selected Service in a tree chart view, may be shown as Fig. 8.
Fig. 8: Your Promotions-Part 3.
• 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 (refer to the CryptuProEco® Contract).
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, Rank of your Cluster, sale count, Sale Average and number of the Promoters may be seen simultaneously. By clicking the legend boxes, you can turn the traces on/off.
• Your History:
Here is your promotion 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, your own Direct Commission, number of articles that you have sold by your promotion and the Sale Average are shown in this graph.
• Contact:
Contacts' information of your Cluster as their Nicknames and Emails are shown in the Fig. 12. You can also export it as an excel data.
Fig. 12: Your Promotions-Part 7.
Register New Service
Here, You can register your business as a Service in the Provider role. 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 | Name of your Service. |
Consumer | Address of your Consumer smart contract, which is deployed before. This contract must be verified on the block explorer, in order to be audit-able by third parties. Please refer to How to Implement Promotion Manager in My Consumer Contract for more information. |
Cluster Share |
You can define the score of the Cluster in percent. In other word, according to the 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. You can set the Cluster Share (or Cluster Score) here. By pressing the “Defaults” button, a predefined setting can be loaded to this field. Data format must be like the below text:
[["2000","0","100"],["4000","100","200"],["6000","200","300"],["8000","300","400"],["10000","400","1000000"]] It is a 5-elements array of ClusterBreak structers (refer to the CryptuProEco® Contract). |
Level Share |
Each cluster has 4 levels that each level has its own share (or its own percentage). By pressing the “Defaults” button, a predefined setting can be loaded to this field. Data format must be like the below text:
[4000,3000,2000,1000] (refer to the CryptuProEco® Contract). |
Z1 (%) | Direct Commission Weight Factor in percent. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Z2 (%) | Cluster Commission Weight Factor in percent. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Min Discount (%) | It is the minimum discount that a Buyer can take benefit of it, if he/she uses a Referral Code. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Max Discount (%) | It is the maximum discount that a Buyer can take benefit of it, if he/she uses a Referral Code. It is the Service maximum discount limit. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Averaging Period (in second) | Number that defines the averaging period for the Promoters over time, which must be specified in seconds (please refer to the item 2-3). By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
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. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Currency | Here is the contract address of acceptable cryptocurrency which the Consumer contract uses to sell articles. It can be any token address or 0x0000000000000000000000000000000000000000 (for specifying native coin, Ex: BNB). |
Fee Payment |
Service registration, has cost which must be paid by a Service Provider to the CryptuProEco®. At the registration time you can specify the way that you pay this fee as one of the following ways:
A) Cash By choosing the cash method, you have to pay the specified fee in BNB, during the registration transaction. B) Sale Percentage Upon selecting Sale Percentage option, You don't pay any fee at the registration time, just you pay it in form of your Service cryptocurrency, when an article is sold by a Promoter (refer to How to Implement Promotion Manager in My Consumer Contract for more information). |
Defaults | You may change the values to their default via this button. |
Submit |
You should finalize your registration after filling all fields. So please click the “Submit” button when you are sure that you have filled all fields. After confirmation of the registration transaction, a message informs it.
“Service registered successfully!” |
Your Provided Services
You can see, your registered Services here, 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 your registered Services here. |
Cluster | You can choose each Cluster of the selected Service. |
Promoter | Each Promoter with their IDs is shown here. You can choose each Promoter of the selected Service to view his/her activity. |
• Service Parameters:
As shown in Fig. 15, parameters of the selected Service can be changed here if it is needed.
Fig. 15: Service Parameters.
Services parameters consist of fields as described in the following table:
field Title | Description |
---|---|
Consumer | Address of your Consumer smart contract, which is deployed before. This contract must be verified on the block explorer, in order to be audit-able by third parties. Please refer to How to Implement Promotion Manager in My Consumer Contract for more information. |
Cluster Share |
You can define the score of the Cluster in percent. In other word, according to the 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. You can set the Cluster Share (or Cluster Score) here. By pressing the “Defaults” button, a predefined setting can be loaded to this field. Data format must be like the below text:
[["2000","0","100"],["4000","100","200"],["6000","200","300"],["8000","300","400"],["10000","400","1000000"]] It is a 5-elements array of ClusterBreak structers (refer to the CryptuProEco® Contract). |
Level Share |
Each cluster has 4 levels that each level has its own share (or its own percentage). By pressing the “Defaults” button, a predefined setting can be loaded to this field. Data format must be like the below text:
[4000,3000,2000,1000] (refer to the CryptuProEco® Contract). |
Z1 (%) | Direct Commission Weight Factor in percent. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Z2 (%) | Cluster Commission Weight Factor in percent. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Min Discount (%) | It is the minimum discount that a Buyer can take benefit of it, if he/she uses a Referral Code. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Max Discount (%) | It is the maximum discount that a Buyer can take benefit of it, if he/she uses a Referral Code. It is the Service maximum discount limit. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Averaging Period (in second) | Number that defines the averaging period for the Promoters over time, which must be specified in seconds (please refer to the item 2-3). By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
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. By pressing the “Defaults” button, a predefined setting can be loaded to this field. |
Dex Router (Optional) | DEX router contract address is used for getting cryptocurrency price. |
Website | Here you can add or change your business website. |
Submit | You can finish your work by pressing the “Submit” button. So, your change has been set. |
• Selected Service, Selected Cluster and Selected Promoter Information:
As you select the desired Service, according to "Your Provided Services", summary of information of the Selected Service, Cluster and Promoter may be shown as Fig. 16 and Fig. 17.
Fig. 16: Information of the selected Service-part 1.
The Selected Service consist of fields as described in the following table:
field Title | Description |
---|---|
ID | Unique ID of the selected Service. |
Name | Name of the selected Service. |
Total Promoters | Number of the total Promoters of the Service. |
Clusters | Number of clusters of the Service. |
Sale | Number of total sales of the Service. |
Average | Sale average of the Service. |
Income (Crypto) | Total income of the Service in cryptocurrency. In this example, TFARTY. |
Income ($) | Total income of the Service in US Dollar (if price is retrievable). |
The Selected Cluster consist of fields as described in the following table:
field Title | Description |
---|---|
ID | Unique ID of the selected Cluster. |
Owner | Nickname of the first Promoter who has formed the Cluster for the first time. |
Promoters | Number of total Promoters of the selected Cluster. |
Sale | Number of total sales of the selected Cluster. |
Average | Sale average of the selected Cluster. |
Income (Crypto) | Total income of the selected Cluster in cryptocurrency. In this example, TFARTY. |
Income ($) | Total income of the selected Cluster in US Dollar (if price is retrievable). |
The Selected Promoter consist of fields as described in the following table:
field Title | Description |
---|---|
ID | Unique ID of the selected Promoter of the Service. |
Nickname | Nickname of the selected Promoter. |
Sale | Number of total sales of the selected Promoter. |
Average | Number of sale average of the selected Promoter. |
Income (Crypto) | Total income of the selected Promoter in cryptocurrency. In this example, TFARTY. |
Income ($) | Total income of the selected Promoter in US Dollar (if price is retrievable). |
Direct Commission | It is the selected Promoter commission in percent. |
Cluster Commission | Cluster Commission percentage of the selected Promoter. |
Total Commission | Sum of Direct Commission and Cluster Commission. |
Referral Discount | Calculated referral discount of the selected Promoter according to his/her activity. It is limited between min/max discount of the Service. |
Contact | This is the email of the selected Promoter. |
As it is shown in Fig. 17, you may see the information of the Selected Service, Selected Cluster and Selected Promoter in the various graphs.
Fig. 17: Information of the selected Service-part 2.
• Cluster Diagram:
The formed Cluster in the desired Service may be shown as Fig. 18. There may be several Clusters for each Service that you can check them all by selecting it in the drop down lists. As it is seen, the Cluster Owner Promoter is located at the top-most level. The others are in the lower levels.
Fig. 18: Cluster Diagram.
• Service History:
Here is the overall Service history which may be shown in Fig. 19.
Fig. 19: Service History.
In this graph you can see the selected Service performance. Income, sale count, sale average and Promoters count may be shown in the current graph. The graphs may be changed by changing the selected Service.
• Cluster History:
In this graph (Fig. 20), you may see the selected Cluster history information. These data contain the Rank, sale count, sale average and Promoters count of the selected Cluster, that may be seen simultaneously. The graphs may be changed by changing the selected Cluster.
Fig. 20: Cluster History.
• Promoter History:
Each Promoter of the selected Service and the selected Cluster has his/her history that is shown in Fig. 21.
Fig. 21: Promoter History.
In the Fig. 21, Cluster Commission (%), Direct Commission (%), sale count and sale average of the selected Promoter is shown. By clicking the legend boxes, you can turn the traces on/off
Also, you can export the contact emails of the members of selected Cluster to an excel file and download it.
Cryptu Lottery (CryptuLotto®) is a secure and reliable lottery platform under Cryptu.io in which gives the players the chance to raise money and win huge $FARTY prizes by buying ticket(s). It's easy, fair, and you can enter as often as you like as long as you have the $FARTY to buy a ticket.
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
• Due to weekly lottery, there is one draw after 48 hours, so you should wait until the final winning number is declared by the platform.
Hint! A 5-day relaxation period is considered in the desired week after final winning number declaration.
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!
View the CryptuLotto® contract for mor information.
Specifications
• Cheaper ticket prices (~$2.49 USDT in $FARTY per ticket) that don't swing wildly with the price of $FARTY.
• Individual user Lottery entry limit: No overall limit, but only 100 tickets can be bought at a time.
• Paying for one ticket will give users a random 6-digit combination with each digit being between 0-9, for e.g. “5-8-3-6-2-1”. Match numbers from the left side to win prizes. 6-tiered prize pool brackets with increasing prize pools as more numbers are matched.
• Manual number selection (optional), so users can use their lucky numbers at buying ticket(s).
• Bulk ticket discounts.
• Lower overall fees.
Ticket Costs and Bulk Purchase Discount
The price of a ticket in $FARTY is approximately ~$2.49 USDT.
The bulk discount reward is for buying larger amounts of tickets. Buying multiple CryptuLotto® tickets at once gives a bulk discount on your purchase. If you're buying only 2 tickets, the discount is negligible, but will add up quickly as you increase the number of tickets to buy in one transaction. The discount only applies to each transaction up to 100 tickets. The discount does not carry over to the next transaction or next round.
How To Win
If the digits on your purchased ticket(s) match the winning numbers drawn at the end of a CryptuLotto® round in correct order (match numbers, from the left side of your ticket), you win a portion of the prize pool.
• Matching even just the first number will win you a small prize.
• Match more numbers to win a share of a larger prize pool.
Winning Criteria
The digits on your ticket should match in the correct order to win. You should match the numbers of your ticket digits with the winning number of the CryptuLotto® round, from the left side in back-to-back form. Matching more numbers means that you have won more portion of the prize pool.
Example:
Suppose that the drawn number is 987654 and you have two tickets with numbers 987454 and 087654.
Ticket 1 (987454):
The first 3 numbers of the ticket and the drawn number is matched, the 4th numbers are not matched and the last 2 numbers are matched again. So only the first 3 numbers are considered as matched numbers..
Ticket 2 (087654):
The first number of the ticket and the drawn number are not matched but the next 5 numbers are matched. So, the ticket will not win anything in spite of matching other 5 right numbers.
The winning situation may be seen as follows:
You will only share in prizes from the highest prize bracket you are eligible for. A ticket matching the first three numbers will only be eligible for prizes from the match-three bracket, and not for the match-one or match-two brackets.
Remember: The digits must match in correct order, starting from left to right in back-to-back form.
Prize Sharing Across Prize Brackets
After a round is drawn, and tickets with matching numbers are determined, the prizes are awarded. The amount won by each ticket will depend on how many other tickets won in the same prize bracket.
For example, if you have the only ticket that matched three numbers in order, and the predetermined share of the prize pool for your bracket was 3000 $FARTY, you'll receive the full 3000 $FARTY. If, however, you and two other people match three numbers in order, the 3000 $FARTY would be split between the three winning tickets, meaning you would receive 1000 $FARTY.
See the CryptuLotto® FAQ for a breakdown of prizes across each bracket.
CryptuLotto® Contract (CryptuLottery V1)
Fork of PancakeSwap Lottery contract by using ChainLinkVRF2 V2 and 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 CryptuPromotionManager 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.
In this instruction, you can learn how to play a lottery in the CryptuLotto® and how to use it.
Start Your Game
You can save lots of $FARTY by taking part in CryptuLotto® and you will experience fun and excitation. More lottery tickets are sold, so there will be larger prize pool. When a prize pool is not won, the next pool will be increased. In other word the longer it's been since someone has won the jackpot, the larger the Lottery prize pool will be. When a round is open, people can buy ticket(s). Each ticket sold increases the prize pool further. Here's how to check the current round's prize pool and remaining time.
As you enter the CryptuLotto® webpage, you will see the amount of money in the pool in $. Also, the remaining time to the drawn of ongoing round or its status will be shown (as Fig. 1).
Fig. 1: Prize Pool and Remaining Time to Drawn.
As time passes, the prize pool is increased by selling more tickets. When a lottery jackpot isn't won, the next round's prize pool will increase; the longer it's been since someone has won the jackpot, the larger the Lottery prize pool will be.
The discount starts at 2 tickets, and scales all the way to 100 tickets where you will save almost 5% on your purchase (4.95% Bulk Discount).
How to Buy Ticket(s)
You only need to have $FARTY for buying tickets. Each ticket costs 2.49 USDT. You can see the value of $FARTY in beginning of the game.
The first step to play lottery in the CryptuLotto® is to connect your wallet (as Fig. 2).
Fig. 2: Connecting Wallet.
The second step is to click the buy ticket button (as Fig. 3).
There is a time between rounds where purchasing tickets isn't possible. Just check back CryptuLotto® after the countdown is over and if that's the case.
Fig. 3: Buy Ticket Button.
Buy Tickets dialog box will be shown as Fig. 4 for you to buy the number(s) of the ticket(s).
Fig. 4: Buy Tickets Dialog Box.
The ticket(s) count(s) shall be entered into the "count" field and also you can have extra discount by enter Referral Code that you have received from the others into the related field.
The third step is to click the "Enable" button (as Fig. 4).
Now you need to confirm and allow permission to the CryptuLotto® to withdraw your tokens at the next purchase steps (as Fig. 5).
Fig. 5: Confirmation Dialog Box.
The forth step is to click “Select Tickets” button (as Fig. 6) After confirmation of permission to withdraw tokens.
Fig. 6: Select Tickets Button.
At fifth step, The cryptulotto® will generate random unique ticket(s) number(s) based on the count that you have entered. Now you can choose your ticket(s) number(s) by pressing “Randomized” Button to generate your numbers randomly again or you can choose and customize your ticket(s) number(s) by clicking each digit (as Fig. 7). Also, you'll get a warning if you create duplicate tickets with same number and it is impossible to have two or more tickets with a unique number at one purchase.
If the numbers are ok, you will click the “Buy” button as Fig. 7 or close Select Tickets dialog box if you change your mind.
Fig. 7: Select Tickets Dialog Box.
The last step is to confirm the buying ticket(s) transaction as Fig. 8 after click the “Buy“ button on the Select Tickets dialog box.
Fig. 8: Buy Ticket(s) Confirmation Dialog Box.
View and Claim Your Ticket(s) After Buying
You can view your ticket(s) after buying them before the round's winning number is drawn as Fig. 9. “Your History“ panel will showing all of your ticket(s) and their numbers. You need to click on each desired round.
Fig. 9: Your History Panel.
As you see, “Your History” panel consist of several columns as described in the following table:
Column Title | Description |
---|---|
Round | The CryptuLotto® round number that you have bought ticket(s). |
Count | The total ticket(s) of each round that you have bought. |
Prize | If you win in each round, you will see your desired prize in this column. The ongoing round do not have any prize so you will see ”N/A” for this round. |
Status |
Each ticket(s) may have 4 statuses: ”Ongoing”, ”Not Winning”, ”Claimable” and ”Claimed”.
If the round is not over, your ticket(s) status will be “Ongoing”. If you have not won anything, so you will not have any prizes and the status will be “Not Winning”. If your ticket(s) numbers have matched, as the Winning Criteria, so the status will be “Claimable”. If you win a round and after withdrawing the prizes, the status will change to ”Claimed”. |
When the ongoing round has ended and the winning numbers are available, you can check your ticket(s) to see if you won. The “Ongoing” Status will be changed to “Claimable” or “Not Winning”. So, you can click on ”Claimable” Button to receive your prize if you won as Fig. 10.
Fig. 10: Claimable Button.
By confirm the received claimed prizes transaction as Fig. 11 after click the “Claimable“ button on the “Your History“ panel, you will receive your prize in your wallet.
Fig. 11: Receive Claimed Prizes Confirmation Dialog Box.
View CryptuLotto® All Rounds History
In “All History“ panel, you can see history of all CryptuLotto® rounds as Fig. 12.
By typing your desired round number in “Round Field” and pressing the Enter key or by using the navigator buttons that can be used to access the next, previous, first, and last rounds, you can see the winning numbers, total prize and total players of each CryptuLotto® round.
As you see, the bottom of “All History” panel consist of several columns as described in the following table:
Column Title | Description |
---|---|
Total Winners | The number(s) of ticket(s) won in selected round of The CryptuLotto®. |
Match Winners | The number(s) of ticket(s) that are matched with the “Winning Number” from 1 to 6 as the Winning Criteria . |
Prize | The total prize for all “Match Winners” in related bracket. |
Each | The prize of each “Match Winner” in USDT in related bracket. |
Hopefully you will be one of the CryptuLotto® winners.
What if there are no winners?
If $FARTY in the prize pool isn't won it doesn't go to waste! Unclaimed $FARTY rolls over to the next CryptuLotto® round.
My ticket matches several numbers but I can't claim a prize.
Tickets are only eligible for prizes if matching numbers from left to right. See the CryptuLotto® documentation for a thorough explanation.
What are the main characteristics of the CryptuLotto®?
CryptuLotto® distributes prizes more widely than other regular network lotteries. It gives each ticket a 1 in 10 chance to match the first number, which means more tickets will at least win prize. More numbers need to be matched sequentially to win more prize.
CryptuLotto® introduces:
• Cheaper ticket prices (~$2.49 USDT in $FARTY per ticket) that don't swing wildly with the price of $FARTY
• Bulk ticket discounts
• 6-tiered prize pool brackets with increasing prize pools as more numbers are matched
• Manual number selection (optional), so users can use their lucky numbers
• Chainlink’s implementation of VRF for true, secure randomness
• Lower overall fees
How are prizes broken down between brackets?
Each bracket's prize pool is a portion of the total $FARTY in each CryptuLotto® round.
Bracket (Numbers matched in order) | $FARTY Allocation |
---|---|
First 1 Number | 2.5% |
First 2 Numbers | 5% |
First 3 Numbers | 10% |
First 4 Numbers | 12.5% |
First 5 Numbers | 20% |
First 6 Numbers | 50% |
Can I exchange my tickets back to $FARTY?
No, once purchased you will not be able to convert your ticket back to $FARTY.
If I win, do I need to manually claim the prize?
Yes, you will need to back to the CryptuLotto® page, connect your wallet and check status under “Your History“. If you have wined, a “Claimable“ link will be appeared.
When does the CryptuLotto® start and finish?
The CryptuLotto® starts in Monday 0 AM UTC and ends in Wednesday 0 AM UTC.
How often is the CryptuLotto® drawn?
The CryptuLotto® drawn is weekly and the draw occurs at the 0 AM UTC Wednesday of each week.
What transaction fee will I pay for buying tickets?
Each ticket purchase will have one transaction. Purchasing a single ticket in a CryptuLotto® will cost a normal amount of fee for a transaction.
However, buying more tickets in that purchase will increase the fee. Buying 100 tickets rather than 1 will not multiply the fee by 100, but may increase the fee amount by 5-6 times (though this varies).
How does the bulk discount work?
The bulk discount reward is for buying larger amounts of tickets. If you're buying only 2 tickets, the discount is negligible, but will add up quickly as you increase the number of tickets to buy in one transaction.
The discount only applies to each transaction up to 100 tickets. The discount does not carry over to the next transaction or next round.
Why can I only buy 100 tickets?
You can only buy a maximum of 100 tickets in one purchase, but you can make multiple purchasesin each round. There's nothing to stop you buying more tickets after your first 100.
If I manually create two or more tickets with the same numbers and they win, am I eligible for prizes for each ticket?
Yes, each ticket is treated as a separate entry to the CryptuLotto®. Keep in mind that the prizes will not be 1:1 though, as each winning ticket you have dilutes each share of the bracket's total prizes.
Hint! You can only buy tickets with the same numbers in separate purchases. In each purchase, you cannot choose two or more tickets with the same numbers and the system will give you the necessary message.
When is $FARTY injected to the CryptuLotto®?
When people buy tickets, the $FARTY they spend is added to the CryptuLotto® pot. In addition, some extra $FARTY is also may be added (injected) to the CryptuLotto® pot by Cryptu.io team.
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 cryptocurrency token without approving any banks or financial institutions and your own tokens are generated in decentralized method.
• Create your cryptocurrency token without any coding and in a few simple steps.
• Minting your cryptocurrency 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 cryptocurrency token without approving any banks or financial institutions and your own tokens are generated in decentralized method.
• Create your cryptocurrency token without any coding and in a few simple steps.
• Minting your cryptocurrency 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.
In this instruction, you can learn how the CryptuMint® works and how to use it.
Token minting is the process of creating new token(s) on a blockchain with a smart contract. You can have your own token(s) with CryptuMint® platform.
As you enter the CryptuMint® webpage, you will see two plans as “Free“ and “Premium“ (as Fig. 1).
Fig. 1: Token Mint Plans.
Free Plan
The first plan is “Free“ that is free of charge. In this plan, the token name cannot be searched in any blockchain networks and the probability of choosing a duplicate token name is very high. Also, a free TOKEN BIRTH CERTIFICATE® (TBC®) will be Issued.
You should click on the word “Free” for entering in this plan and after that you should connect your wallet by press ”Connect Wallet” button as Fig. 2.
Fig. 2: Connect Wallet Button.
As soon as your wallet is connected, the page would be viewable as Fig. 3. In this point you will see two separate sections. The right side is the “Your Minted Tokens“ that generated by CryptuMint®, and the left side is used to mint and generate new tokens. You can also change the blockchain network in the “Select Network“ dialog box as shown in Fig. 4 by clicking the network icon shown in Fig. 3.
Fig. 3: Plan Appearance With Connected Wallet.
Fig. 4: Select Network Dialog Box.
Currently, there are two types of tokens that can be minted by the CryptuMint®, ERC20 standard and liquidity generator token types. By selecting the token type, you will see various fields in minting panel that you must fill in carefully to generate the token.
“Standard” token type minting panel consist of several fields as described in the following table:
Field Title | Description |
---|---|
Token Name | The name that you have chosen for your token. |
Token Symbol | The symbol that you have chosen for your token. |
Decimals | The number of decimals (portions) that is acceptable. |
Total Supply | The total amount of tokens that have been created or mined. |
“Liquidity Generator” token type minting panel consist of several fields as described in the following table:
Field Title | Description |
---|---|
Token Name | The name that you have chosen for your token. |
Token Symbol | The symbol that you have chosen for your token. |
Decimals | The number of decimals (portions) that is acceptable. |
Total Supply | The total amount of tokens that have been created or mined. |
Router | It is your desired DEX that your liquidity is located on that decentralised exchanger. Others can exchange your token in this DEX. |
Transaction Reward Fee (%) | Transaction fee (%) to pay dividend to holders. This reward will be collected by your token contract and used to pay dividend to holders. |
Transaction Liquidity Generator Fee (%) | The percentage of each transaction that will be added to the liquidity pool. |
Marketing Fee (%) | Marketing Fee (%) will be sent to your wallet. Marketing Fee is used to help your project growing. |
Marketing Address | Your valid wallet address. |
After all fields in minting panel are filled in carefully, you should press the ”Creat Token” button as shown in Fig. 5 to pay network fee for deploying contract and confirm the ”Deploy a Contract” transaction as shown in Fig. 6 for generating the token.
Fig. 5: Create Token Button.
Fig. 6: Deploy A Contract Confirmation Dialog Box.
Now you can see your minted token specifications panel as Fig. 7 consists of several fields as Certificate Code, Name, Symbol, Total Supply, Decimals, Type, Network, Contract Address, Owner Address and the Transaction Hash.
Fig. 7: Minted Token Specification Panel.
Also, you can click on your “Contract Address” as shown in Fig. 7, so the minted token would be checked in the selected network as Fig. 8.
Fig. 8: Minted Token Page In Blockchain Network.
At the buttom of minted token specification panel, your own TBC® is shown as Fig. 9 that is downloadable as a PNG file format by press “Download“ button.
Fig. 9: Your Own TBC®.
Premium Plan
The second plan is “Premium“ that is not free of charge. By Choosing Premium Plan, our engine will search the selected blockchain networks to find any occurrence of your token's name in order to choose a unique name. Also, a free TOKEN BIRTH CERTIFICATE® (TBC®) will be Issued and a TOKEN UNITY CERTIFICATE® (TUC®) will be available to purchase.
You should click on the word “Premium” for entering in this plan and after that you should connect your wallet by press ”Connect Wallet” button as Fig. 2.
As soon as your wallet is connected, the page would be viewable as Fig. 10. So you should select the desired “Payment Currency“ from dropdown list and press the “Pay“ button to pay CryptuMint® cost to start the premium minting.
Fig. 10: Premium Plan Payment Appearance.
The page would be viewable as Fig. 3 after confirmation of the payment transaction and due to confirmed process. Except searching the token name and symbol in various blockchain networks, the Premium and Free plans procedures are the same. So, you can use the description of all steps in Free plan.
In addition, Premium plan displays three states in the “Token Name” field filling step (after pressing the Enter key or leaving the field) to help you choose a unique name, as ”Searching Network...”, ”Exist!” and ”Available At This Moment!”. These states are not available in test networks and only works in main networks.
Hint! If ”Available At This Moment!” is displayed, it means you can choose a unique name for your token. And please note that the token name and the symbol search results are completely depends on the conditions of blockchain networks during search process. Cryptu.io will not be responsible for the accuracy or completeness of the results in which received from these networks.
Do you like to have TUC® too in which guarantees your minted token has unique name over famous crypto platforms? If the answer is “yes” you can select “Get A Certificate" as Fig. 11 after minting your own token and receiving related TBC® in Premium plan.
Fig. 11: Get A Certificate Section.
So, you will guide to search panel as fig 12. In this section, you should enter TBC®/TUC® code or contract address in the “Code/Address“ box and press “Search“ Button to start the search process.
Fig. 12: Search Panel.
Then the search results consist of the Network (primary selected), Name, Symbol and the TBC® (available if published) of minted token are shown in result section as Fig. 13. Also, in the next section, our platform will search different networks and show you in which of these networks (badges) you can get TUC®.
Fig. 13: Search Result Appearance.
The bright badge means your token TUC® is available to purchase in that network and the disabled badge means your token name is exist in that network and TUC® isn’t available for purchasing. You may choose each of available badges and the related certificate will be published after purchasing and paying the required amount of currencies.
So you can choose several networks in which the TUC® will be available in them as shown in Fig. 14. The selected badges will turn into ticks and the “Amount To Pay“ in USDT will be shown at the bottom. Now the “Purchase“ button should be pressed.
Fig. 14: Selected Badges Appearance.
You will be directed to the payment section that is shown in Fig. 15 and you should connect your wallet and choose the desired network (if nedded) for payment. Now the desired “Payment Currency“ should be selected from dropdown list as Fig. 16 that is equal to the “Amount To Pay“ and the “Pay“ button should be pressed.
Fig. 15: Connect Wallet Section.
Fig. 16: Payment Panel.
Since your wallet is connected and “Pay“ button is pressed according the previous steps, so you should confirm the currency transfer request as Fig. 17.
Fig. 17: Currency Transfer Request Dialog Box.
Now you can see your token TUC® specifications panel as Fig. 18 consists of several fields as Certificate Code, Name, Symbol, Network and the Contract Address. At the buttom of token TUC® specification panel, your own TUC® is shown that is downloadable as a PNG file format by press “Download“ button.
Fig. 18: Token TUC® Specification Panel And Your Own TUC®.
As it is shown in above figure, your own TUC® contains the specifications and the selected badge(s) you have purchased and your token name is unique in those network(s).
Cryptu Token Query (CryptuQuery®) is a comprehensive platform under Cryptu.io in which the authenticity and validity of certificates, that has been generated by Cryptu.io, can be checked. Also, if a TUC® has not been issued for your token by our website, you can purchase it through this section. The QR code of TBC®/TUC® or token contract address may be checked in CryptuQuery® then the system will show you whether TBC® or TUC® was issued for your token, and if it was issued, its authenticity can be checked.
In this instruction, you can learn how the CryptuQuery® works and how to use it.
As you enter the CryptuQuery® webpage, you will see the platform as Fig. 1.
Fig. 1: CryptuQuery® Webpage Appearance.
Authenticity Check
You may want to check authenticity of published TBC®/TUC® by Cryptu.io in CryptuQuery®. So, you should enter Token Birth/Unity Certificate code or token contract address in related “Code/Address” box as shown in fig. 1.
If you entered Token Birth/Unity Certificate code, you only need to press the "Search" button as shown in Fig. 2 and if you entereand token contract address, you should leave the box to activate the "Network" drop down list, select correct network related to your token and then press the “Search” button as shown in Fig. 3 to start the search process.
Please remember that the correct format for entering code/address in related box must be followed, otherwise the system will show you the appropriate message.
Fig. 2: TBC®/TUC® Code Search.
Fig. 3: Token Contract Address Seacrh.
If TBC®/TUC® in which has been published by Cryptu.io, so the “Token Unity Certificate (TUC)” or “Token Birth Certificate (TBC)” would be in available mode in search result as shown in Fig. 4. If you press the “Available” button, you can check authenticity and validity of certificates by viewing a copy of the published certificate in PNG file format.
Fig. 4: CryptuQuery® Code/Address Search Result.
Also, remember that you can check the authenticity of published TBC®/TUC® by scanning the QR code on them.
Purchase TUC®
You may want to purchase a TUC® for your token from Cryptu.io in CryptuQuery®. So, you should enter TBC® code or contract address of your token in related “Code/Address” box as previously explained and then press the “Search” button to start the search process.
Then the search results consist of the Network (primary selected), Name, Symbol and the TBC® (available if published) of your token are shown in result section as Fig. 5. Also, in the next section, our platform will search different networks and show you in which of these networks (badges) you can get TUC®.
Fig. 5: Search Result Appearance.
The bright badge means your token TUC® is available to purchase in that network and the disabled badge means your token name is exist in that network and TUC® isn’t available for purchasing. You may choose each of available badges and the related certificate will be published after purchasing and paying the required amount of currencies.
So you can choose several networks in which the TUC® will be available in them as shown in Fig. 6. The selected badges will turn into ticks and the “Amount To Pay“ in USDT will be shown at the bottom. Now the “Purchase“ button should be pressed.
Fig. 6: Selected Badges Appearance.
You will be directed to the payment section that is shown in Fig. 7 and you should connect your wallet and choose the desired network (if nedded) for payment. Now the desired “Payment Currency“ should be selected from dropdown list as Fig. 8 that is equal to the “Amount To Pay“ and the “Pay“ button should be pressed.
Fig. 7: Connect Wallet Section.
Fig. 8: Payment Panel.
Since your wallet is connected and “Pay“ button is pressed according the previous steps, so you should confirm the currency transfer request as Fig. 9.
Fig. 9: Currency Transfer Request Dialog Box.
Now you can see your token TUC® specifications panel as Fig. 10 consists of several fields as Certificate Code, Name, Symbol, Network and the Contract Address. At the buttom of token TUC® specification panel, your own TUC® is shown that is downloadable as a PNG file format by press “Download“ button.
Fig. 10: Token TUC® Specification Panel And Your Own TUC®.
As it is shown in above figure, your own TUC® contains the specifications and the selected badge(s) you have purchased and your token name is unique in those network(s).
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 cryptocurrency, 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!