#################################### Implementation of DrawChain #################################### Overview ============================================ .. image:: ../img/PERSONA/DrawChain.png -------------------------------------------------------------------------------------------------------------------------------- Setting Up DrawChain ============================================ | You can configure the conditions for running DrawChain. | Configuration is possible by registering a contract that inherits the IDrawChainAuthorizer interface. | Also, by registering a contract that inherits the IDrawChainPostProcessor interface, you can configure the behavior after Draw. ■ Functions for Publishers 1. Create a contract to set conditions for running DrawChain: Create a contract that implements the IDrawChainAuthorizer interface (IDrawChainAuthorizer.sol):: @param drawChainId DrawChain ID @param presetId Preset number (freely defined within the implementation contract) @param personaId PERSONA Id function authorizeDraw (uint256 drawChainId, uint256 presetId, uint256 personaId) external view returns (bool); Refer to the environment information for the interface file. 2. Register DrawChain Register the contract created in step 1 in AuthorizerInfo. Set the address of the created contract and presetId in AuthorizerInfo. The usage of presetId can be freely defined within the implementation contract. Function to register DrawChain (Drawchain.sol):: @param squareKey SquareKey associated with DrawChain @param _authorizers List of authorizers @return DrawChain ID function newDrawChain(uint256 squareKey, AuthorizerInfo[] calldata _authorizers) public returns (uint256) AuthorizerInfo[]:: struct AuthorizerInfo { @notice Address of the IDrawChainAuthorizer contract address authorizer; @notice Preset ID of the IDrawChainAuthorizer contract uint256 presetId; } Setting Active and Inactive States -------------------------------------------- | During the initial registration, draw capability is set to true. | DrawChain creators can control the execution of draw. They can change the state to active (true) or inactive (false). Function to set the active and inactive states of DrawChain (Drawchain.sol): @param drawChainId DrawChain ID @param active true: draw is possible, false: draw is not possible function deactivateDrawChain(uint256 drawChainId, bool active) public; 3. Create a Contract to Define the Behavior after Executing DrawChain ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Create a contract that implements the IDrawChainPostProcessor interface(IDrawChainPostProcessor.sol):: @notice Executes post-processing after a successful Draw. @param drawChainId DrawChain ID @param personaId Persona ID @param personaOwner The owner of the Persona at the time of successful Draw @param processorData DrawChain.attach()時に指定するコントラクト特有のデータ @return true: Prize distribution is complete (records the distribution date), false: No prize distribution took place function process(uint256 drawChainId,uint256 personaId,address personaOwner,uint256 processorData) external returns(bool); | Interface files refer to the environmental information. | If post-processing after Draw is not required, steps 3 and 4 are unnecessary. 4. Register and Deregister the PostProcessor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Configure the DrawChain created in the previous step with the created contract. | Specify the ID of the target DrawChain and the contract address of the DrawChainPostProcessor to be configured. | The usage of data can be freely defined within the implementation contract. Function to register the DrawChainPostProcessor(Drawchain.sol):: @param drawChainId DrawChain ID @param _addr Address of the PostProcessor @param data function attachPostProcessor(uint256 drawChainId,address _addr,uint256 data) Function to deregister the DrawChainPostProcessor(Drawchain.sol):: @param drawChainId DrawChain ID @param _addr Address of the PostProcessor @param data function detachPostProcessor(uint256 drawChainId,address _addr,uint256 data) -------------------------------------------------------------------------------------------------------------------------------- Other DrawChain Functions ============================================ Returning an Array of DrawChain IDs for Which a Specific PERSONA Can Draw (Drawchain.sol):: @param from Starting ID of DrawChains to inspect (inclusive) @param until Ending ID of DrawChains to inspect (inclusive) @param limit Limit the search to this many successful DrawChains (maximum number of elements to return in the array) @param personaId PERSONA ID to draw DrawChains @return Array of DrawChain IDs where draw is successful function availables(uint256 from, uint256 until, uint256 limit, uint256 personaId) public view returns (uint256[] memory) .. admonition:: Regarding Specified Ranges Be cautious when using availables() to search over a wide range, as it may result in gas exhaustion. Getting DrawChain Information (Drawchain.sol):: @param fromId Starting DrawChain ID @param count Number of DrawChain information to retrieve @return Array of DrawChainInfo function getDrawChain(uint256 fromId, uint256 count) public view returns (DrawChainInfo[] memory) DrawChainInfo:: struct DrawChainInfo { uint256 id; uint32 squareKey; uint8 active; uint8 pad1; uint16 pad2; uint64 pad3; uint128 pad4; } Returning the Number of Draws (History Count) for Each DrawChain (Drawchain.sol):: @param drawChainId DrawChain ID @return Number of draws (history count) function drawHistoryCountByDrawChain(uint256 drawChainId) public view returns (uint256) Returning the Draw History for Each DrawChain (Batch Version) (Drawchain.sol):: @param drawChainId DrawChain ID @param fromIdx Starting index (inclusive) @param count Number of draw histories to retrieve @return Array of draw histories function drawHistoryByDrawChain(uint256 drawChainId, uint256 fromIdx, uint256 count) public view returns (History[] memory) Returning the Number of Draws (History Count) for Each PERSONA (Drawchain.sol):: @param personaId PERSONA Id @return Number of draws (history count) function drawHistoryCountByPersona(uint256 personaId) public view returns (uint256) Returning the Draw History for Each PERSONA (Batch Version) (Drawchain.sol):: @param personaId PERSONA Id @param fromIdx Starting index (inclusive) @param count Number of draw histories to retrieve @return Array of draw histories function drawHistoryByPersona(uint256 personaId, uint256 fromIdx, uint256 count) public view returns (History[] memory) History:: struct History { @notice History ID, same as the value returned by draw() uint256 id; @notice DrawChain Id uint256 drawChainId; @notice PERSONA Id uint256 personaId; @notice Owner of the PERSONA at the time of the draw address personaOwner; @notice Timestamp when the draw occurred uint128 drawnOn; @notice Timestamp when the delivery was made uint128 deliveredOn; } Returning the Number of Draws (History Count) for Each DrawChain and PERSONA (Drawchain.sol):: @param drawChainId DrawChain ID @param personaId PERSONA Id @return Number of draws (history count) function drawHistoryCountByDrawChainAndPersona(uint256 drawChainId, uint256 personaId) public view returns (uint256) Returning the Draw History for Each DrawChain and PERSONA (Batch Version) (Drawchain.sol):: @param drawChainId DrawChain ID @param personaId PERSONA Id @param fromIdx Starting index (inclusive) @param count Number of draw histories to retrieve @return Array of draw histories function drawHistoryByDrawChainAndPersona(uint256 drawChainId, uint256 personaId, uint256 fromIdx, uint256 count) public view returns (History[] memory) Returning the Number of Draws (History Count) for Each PERSONA Owner (Drawchain.sol):: @param personaOwner Persona owner address @return Number of draws (history count) function drawHistoryCountByPersonaOwner(address personaOwner) public view returns (uint256) Returning the Draw History for Each PERSONA Owner (Batch Version) (Drawchain.sol):: @param personaOwner Persona owner address @param fromIdx Starting index (inclusive) @param count Number of draw histories to retrieve @return Array of draw histories function drawHistoryByPersonaOwner(address personaOwner, uint256 fromIdx, uint256 count) public view returns (History[] memory) Returns PostProcessor information set for each DrawChain(Drawchain.sol):: @param drawChainId DrawChain ID @return PostProcessorInfo function listPostProcessor(uint256 drawChainId) public view override returns(PostProcessorInfo[] memory) -------------------------------------------------------------------------------------------------------------------------------- Executing DrawChain ============================================ 1. Drawing a DrawChain Contract: Drawchain ■ Function Executed by Users When Performing Operations Function to draw a DrawChain (Drawchain.sol): @param drawChainId DrawChain ID @param personaId PERSONA ID @return 0: Draw failed. Non-zero: Index of the history function draw(uint256 drawChainId, uint256 personaId) public returns (uint256) 2. Calling the DrawChain creator (Publisher) when distributing prizes and register the timestamp when delivery of prizes is made. ■ Function for Publishers Function to register a timestamp (Drawchain.sol): @param historyId History ID returned when draw is successful function delivered(uint256 historyId) .. admonition:: About Timestamps | The delivered() function is optional. | When called upon delivering prizes, a timestamp is registered in the deliveredOn field of the History structure. | If it is not executed, the only consequence is that the delivery history will not be stored at the blockchain level. | The advantages of performing this include: | - Timestamps are set at the blockchain level and cannot be tampered with | - It can be used for future integration with other programs on the smart contract -------------------------------------------------------------------------------------------------------------------------------- Implemented IDrawChainAuthorizers ============================================ | The following contracts currently implement the IDrawChainAuthorizer interface and are available for use. | To enable them, you need to set the contract in the AuthorizerInfo during DrawChain registration. Contract to Limit the Ability Values of PERSONAs that Can Draw (DrawAbilityLimitter.sol) ==================================================================================================================================== | (DrawAbilityLimitter.sol) | The ability values need to be set by the square key owner in advance. | After setting the values, set the contract in AuthorizerInfo during DrawChain registration. | If the ability values of the PERSONA to be drawn are within the set range, drawing becomes possible. Functions for Registration:: @param limit Set the ability value limits. Limit[6] corresponds to FOR, ABS, DFT, MND, INT, EXP, in that order. @return numPresets Registration number function newPreset(Limit[6] calldata limit) public returns (uint256) Functions for Modification:: @notice Specify the registration number for presetId. Only the sender at the time of newPreset can update. @param presetId Registration number @param limit Set the ability value limits. Limit[6] corresponds to FOR, ABS, DFT, MND, INT, EXP, in that order. function alterPreset(uint256 presetId, Limit[6] calldata limit) Values:: uint256 public numPresets; // Registration number, incremented and assigned automatically by newPreset. mapping(uint256 => Limit[6]) public preset; // Mapping of registration numbers to ability value limit contents mapping(uint256 => address) public presetOwner; // Mapping of registration numbers to the sender at the time of newPreset Limit Structure:: struct Limit { uint16 min; uint16 max; } Contract to Limit PERSONA Categories that Can Draw (DrawPersonaCategoryLimitter.sol) ==================================================================================================================================== | (DrawPersonaCategoryLimitter.sol) | Set the contract in AuthorizerInfo during DrawChain registration and specify the categories you want to assign to presetId. | If the categories included in the PERSONA Id of the drawing PERSONA match the specified categories in presetId, drawing becomes possible. Contract to Limit the Number of Draws (DrawQuantityLimitter.sol) ==================================================================================================================================== | (DrawQuantityLimitter.sol) | Set the contract in AuthorizerInfo during DrawChain registration and specify the number of draws for presetId. | Drawing is possible if the number of draws made is less than the specified number of draws. Contract to Limit the Caller of draw() to Subscribers of the Square Key Associated with DrawChain (DrawFollowerLimitter.sol) ==================================================================================================================================== | (DrawFollowerLimitter.sol) | Set the contract in AuthorizerInfo during DrawChain registration. | Determine whether the user who made the draw is a follower of the square key associated with the DrawChain. | If they are a follower, drawing becomes possible | Subscribers of the square key can be placed on a blacklist. | Once on the blacklist, Subscribers will be unfollowed and cannot follow again. | To re-follow, they need to have their registration removed from the blacklist. | Registration and removal from the blacklist can be done by the owner of the square key. | 【SquareSupplement.sol】 Functions to Register or Remove from the Blacklist:: @param squareKey Target square key @param _address Follower address @param isBlack true: Register, false: Remove from the blacklist function setBlackList(uint256 squareKey, address _address, bool isBlack) public Contract to Limit the Number of draw() Calls by the Same PERSONA (DrawCountLimitter.sol) ==================================================================================================================================== | (DrawCountLimitter.sol) | Set the contract in AuthorizerInfo during DrawChain registration and specify the number of draws for presetId. | Drawing is possible if the number of draws made by the same persona is less than the specified number of draws. Contract to Limit draw() Calls to Specific PERSONAs (DrawPersonaLimitter.sol) ==================================================================================================================================== | (DrawPersonaLimitter.sol) | Specify the PERSONAs that you want to enable for draw() using newPreset. | Set the contract in AuthorizerInfo during DrawChain registration and assign the return value from the previous setup to presetId. | Drawing is possible if the specified PERSONA is included in the designated Preset. newPreset:: @param personas Array of PERSONA IDs to be registered @return numPresets Registration number function newPreset(uint256[] calldata personas) public returns (uint256) Contracts that restrict the range of draw()-able Persona IDs. ==================================================================================================================================== | (DrawPersonaIdRangeLimiter.sol) | newPreset to create a new preset. | addRangeToPreset to add a new range to the specified preset. | Delete the specified preset with resetPreset. | If the specified Preset contains the target PERSONA, it is drawable. newPreset:: @notice Creates a new preset and returns its ID. @return ID of the new preset created function newPreset() public returns (uint256) addRangeToPreset:: @notice Add a new range to the specified preset @param id Preset ID to which the range is added @param min Min Persona ID of the range @param max max max Persona ID of the range function addRangeToPreset(uint256 id, uint256 min, uint256 max) public resetPreset:: @notice Resets the range associated with the specified preset ID @param id Preset ID to reset function resetPreset(uint256 id) public Implemented IDrawChainPostProcessor ============================================ | The currently available contracts that implement the IDrawChainPostProcessor interface are as follows. | To enable it, you need to attach it to DrawChain. A contract that transfers the specified PERSONA after draw to the specified address ============================================================================================ | (PersonaCollector.sol) | Set the forwarding destination address in data when attaching. | Transfer the personaId argument at draw to the address specified above. | It is necessary to approve PERSONA to the DrawChain contract before executing draw.