Requirements for Rule designer before releasing it
Before a rule can be useful, output tokens must allow the rule to mint their tokens. So, the rule designer must negotiate with the output games and gather their approvals for the rule. After minting rights have been given through the CraftableOut.canMint( ... ) function, the rule can be used to craft and redeem transactions.
Usage Requirements for User
To craft...
For the user to be able to use the crafting rule services, they must:
Give transfer approval in the input and output contracts to the crafting rule address. this should be facilitated through the crafting web-app.
Have enough of the tokens to satisfy the needs of the crafting rule.
Call the craft( ... ) function with the order of tokens mentioned in the definition.
To redeem...
For the user to redeem, in addition to approvals, they must
Already have crafted the output tokens they want to redeem
Call the redeem( ... ) function with the order of tokens mentioned in the definition.
Understanding how the crafting rule contract works
To implement the crafting rule, you can opt to code it yourself for the full customization and flexibility. If you don't feel like coding, we offer you a no-code tool to generate the crafting rule for you.
In all cases, all you have to code - if you intend to use the coding approach - are four functions
The constructor
In your constructor, you must initialize the crafting rule with the lists of input and output tokens you intend to use in your rule.
constructor( ... ) {CraftingRule( [list of input contract addresss], [list of output contract addresses ] )}
The item orders
There are two functions to implement to validate the order of user inputs for the craft( ... ) and redeem( ... )
_inputItemOrderValid(address[] addrs, uint256[] classes)
it should return true only if the input order is the same as the definition file.
my-meal-rule.sol
...function_inputItemOrderValid(address[] memory addrs,uint256[] memory classes) internalviewoverridereturns (bool) {//MealRule: bag must have 2 items and 2 classesif (!(addrs.length ==2&& classes.length ==2)) returnfalse;// MealRule: first item must be falafelif (!(addrs[0] == FALAFEL_INGREDIENT)) returnfalse;if (!(classes[0] ==1)) returnfalse;// MealRule: second item must be condimentif (!(addrs[1] == CONDIMENT_INGREDIENT)) returnfalse;returntrue;}...
_outputItemOrderValid(address[] addrs, uint256[] classes)
it should return true only if the output order is the same as the definition file.
my-meal-rule.sol
...function_outputItemOrderValid(address[] memory addrs,uint256[] memory classes) internalviewoverridereturns (bool) {//MealRule: bag must have 2 items and 2 classesif (!(addrs.length ==2&& classes.length ==2)) returnfalse;// MealRule: first item must be sandwichif (!(addrs[0] == SANDWICH)) returnfalse;if (!(classes[0] ==1)) returnfalse;// MealRule: second item must be napkinif (!(addrs[1] == NAPKIN)) returnfalse;returntrue;}...
The mapping rule
The mapping rule defines the buisness rules in place to transform the inputs provided to the outputs in questions. it could be simple if-else conditions for filters or complicated math operations to compute the output attribute value from input attribute values.
The mapping rule rule(Bag inBag, ItemAttributes[] inAttributes) takes the input in the form of structs. It should return:
list of output addresses outAddrs
list of output classes outClasses
list of output balances outBalances
list of output attributes in the form of ItemAttributes structs.
functionrule ( ... ) ... {// [1] initialize output lists for addresses, classes, balances, balances// [2] logic to compute output balances and attributes from input values}
[1] Initialization
functionrule ( ... ) ... { ...// [1] initialize the output lists// OUTPUT ADDRESSES outAddrs =newaddress[](2); outAddrs[0] = SANDWICH; outAddrs[1] = NAPKIN;// OUTPUT CLASSES outClasses =newuint256[](2); outClasses[0] =1; // the first token should be a Falafel token// example of making the output class choice based on an input// if the falafel is big, we need a textile napkinif (falafelAttributes.attributes[1] >16) { outClasses[1] =2; } else { outClasses[1] =1; }// OUTPUT BALANCES outBalances =newuint256[](2);// one sandwich outBalances[0] =1;// if we have taratour, we need two napkinsif (condiment.class ==1) { outBalances[1] =2; } else { outBalances[1] =1; } ...}
[2] Computing output balances and attributes
The jth attribute of the ith input token can be accessed via inAttributes[i].attributes[j]
The balance of the jth input token can be accessed by
Item memory myJthToken =_getItem(inBag,1);// => access through myJthToken.balance
an example of some output logic code for attributes
functionrule ( ... ) ... { ...// [2] logic to compute output// if we used tahini it expiresif (condiment.class ==3) { outAttributes[0].attributes[3] =1; } else { outAttributes[0].attributes[3] =0; } ...}
Performs the crafting of the input tokens to the output tokens. It performs the following operations in order:
Converts the list into a Bag struct and ItemAttributes list.
Generate the output templates and attributes according to the rule(...) implemented by the rule developer.
Transfers the input tokens from the user wallet to the rule wallet.
Mint and/or transfer the output tokens according to the disclosed mapping rule to the user wallet.
Stores the input tokens and tags them with the output bag of tokens. This will help reverse the operation in redeeming.
Generates Crafted events, which has the CraftingHash. the crafting hash acts as the invoice ID for the crafting operation. The hash is a function of the input bag presented.
Performs the redeeming the input tokens owned by the contract by returning the output tokens previously crafted. It performs the following operations in order:
Converts the list into a Bag struct.
Recover the input bag previously pointed to by the signature of the output bag.
Transfer the input tokens from the contract wallet to the user wallet.