ℹ️LinksRepo

A Links Repo of Drag-Along and Tag-Along sale.

Name

LinksRepo

Dependent Contract

IRegisterOfMembers, IRegisterOfShares, DealsRepo, RulesParser, SharesRepo

API

API
Function Description
function addDragger(
    Repo storage repo, 
    bytes32 rule, 
    uint256 dragger, 
    IRegisterOfMembers _rom
) public;

Add Sellers and Linking rules for Sale Links Repo.

function removeDragger(
    Repo storage repo, 
    uint256 dragger
) public; 

Remove Seller from Sale Links Repo.

function addFollower(
    Repo storage repo, 
    uint256 dragger, 
    uint256 follower
) public; 

Add the user number of follower into Sale Links Repo.

function removeFollower(
    Repo storage repo, 
    uint256 dragger, 
    uint256 follower
) public;

Remove the user number of follower into Sale Links Repo.

function isDragger(
    Repo storage repo, 
    uint256 dragger, 
    IRegisterOfMembers _rom
) public view returns (
    bool
);

Query whether a specific numbered user is the seller of Sale Link.

function getLinkRule(
    Repo storage repo, 
    uint256 dragger, 
    IRegisterOfMembers _rom
) public view returns (
    RulesParser.LinkRule memory
); 

Get the Link Rule corresponding to the seller.

function isFollower(
    Repo storage repo, 
    uint256 dragger, 
    uint256 follower,
    IRegisterOfMembers _rom
) public view returns (
    bool
);

Query whether a specific numbered user is a follower of a specific seller.

function getDraggers(
    Repo storage repo
) public view returns (
    uint256[] memory
);

Get the number list of all sellers.

function getFollowers(
    Repo storage repo, 
    uint256 dragger, 
    IRegisterOfMembers _rom
) public view returns (
    uint256[] memory
); 

Get the list of all follower user numbers for a specific seller.

function priceCheck(
    Repo storage repo,
    DealsRepo.Deal memory deal,
    IRegisterOfShares _ros,
    IRegisterOfMembers _rom
) public view returns (
    bool
);

Query whether the price of a specific transaction satisfies the requirements of Sales Links Rule.

Source Code:

LinksRepo
// SPDX-License-Identifier: UNLICENSED

/* *
 * Copyright (c) 2021-2023 LI LI @ JINGTIAN & GONGCHENG.
 *
 * This WORK is licensed under ComBoox SoftWare License 1.0, a copy of which 
 * can be obtained at:
 *         [https://github.com/paul-lee-attorney/comboox]
 *
 * THIS WORK IS PROVIDED ON AN "AS IS" BASIS, WITHOUT 
 * WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
 * TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. IN NO 
 * EVENT SHALL ANY CONTRIBUTOR BE LIABLE TO YOU FOR ANY DAMAGES.
 *
 * YOU ARE PROHIBITED FROM DEPLOYING THE SMART CONTRACTS OF THIS WORK, IN WHOLE 
 * OR IN PART, FOR WHATEVER PURPOSE, ON ANY BLOCKCHAIN NETWORK THAT HAS ONE OR 
 * MORE NODES THAT ARE OUT OF YOUR CONTROL.
 * */

pragma solidity ^0.8.8;

import "../comps/books/rom/IRegisterOfMembers.sol";
import "../comps/books/ros/IRegisterOfShares.sol";

import "./DealsRepo.sol";
import "./RulesParser.sol";
import "./SharesRepo.sol";

library LinksRepo {
    using EnumerableSet for EnumerableSet.UintSet;
    using RulesParser for bytes32;

    enum TriggerTypeOfAlongs {
        NoConditions,
        ControlChanged,
        ControlChangedWithHigherPrice,
        ControlChangedWithHigherROE
    }

    struct Link {
        RulesParser.LinkRule linkRule;
        EnumerableSet.UintSet followersList;
    }

    struct Repo {
        // dragger => Link
        mapping(uint256 => Link) links;
        EnumerableSet.UintSet  draggersList;
    }

    modifier draggerExist(Repo storage repo, uint dragger, IRegisterOfMembers _rom) {
        require(isDragger(repo, dragger, _rom), "LR.mf.draggerExist: not");
        _;
    }

    // ###############
    // ## Write I/O ##
    // ###############

    function addDragger(Repo storage repo, bytes32 rule, uint256 dragger, IRegisterOfMembers _rom) public {
        uint40 groupRep = _rom.groupRep(dragger);
        if (repo.draggersList.add(groupRep))
            repo.links[groupRep].linkRule = rule.linkRuleParser();
    }

    function removeDragger(Repo storage repo, uint256 dragger) public {
        if (repo.draggersList.remove(dragger))
            delete repo.links[dragger];
    }

    function addFollower(Repo storage repo, uint256 dragger, uint256 follower) public {
        repo.links[dragger].followersList.add(uint40(follower));
    }

    function removeFollower(Repo storage repo, uint256 dragger, uint256 follower) public {
        repo.links[dragger].followersList.remove(follower);
    }

    // ################
    // ##  查询接口  ##
    // ################

    function isDragger(Repo storage repo, uint256 dragger, IRegisterOfMembers _rom) 
        public view returns (bool) 
    {
        uint40 groupRep = _rom.groupRep(dragger);
        return repo.draggersList.contains(groupRep);
    }

    function getLinkRule(Repo storage repo, uint256 dragger, IRegisterOfMembers _rom) 
        public view draggerExist(repo, dragger, _rom)
        returns (RulesParser.LinkRule memory) 
    {
        uint40 groupRep = _rom.groupRep(dragger);
        return repo.links[groupRep].linkRule;
    }

    function isFollower(
        Repo storage repo, 
        uint256 dragger, 
        uint256 follower,
        IRegisterOfMembers _rom
    ) public view draggerExist(repo, dragger, _rom) 
        returns (bool) 
    {
        uint40 groupRep = _rom.groupRep(dragger);
        return repo.links[groupRep].followersList.contains(uint40(follower));
    }

    function getDraggers(Repo storage repo) public view returns (uint256[] memory) {
        return repo.draggersList.values();
    }

    function getFollowers(Repo storage repo, uint256 dragger, IRegisterOfMembers _rom) 
        public view draggerExist(repo, dragger, _rom) returns (uint256[] memory) 
    {
        uint40 groupRep = _rom.groupRep(dragger);
        return repo.links[groupRep].followersList.values();
    }

    function priceCheck(
        Repo storage repo,
        DealsRepo.Deal memory deal,
        IRegisterOfShares _ros,
        IRegisterOfMembers _rom
    ) public view returns (bool) {

        RulesParser.LinkRule memory lr = 
            getLinkRule(repo, deal.head.seller, _rom);

        if (lr.triggerType == uint8(TriggerTypeOfAlongs.ControlChangedWithHigherPrice)) 
            return (deal.head.priceOfPaid >= lr.rate);

        SharesRepo.Share memory share = 
            _ros.getShare(deal.head.seqOfShare);

        if (lr.triggerType == uint8(TriggerTypeOfAlongs.ControlChangedWithHigherROE))
            return (_roeOfDeal(
                deal.head.priceOfPaid, 
                share.head.priceOfPaid, 
                deal.head.closingDeadline, 
                share.head.issueDate) >= lr.rate);

        return true;
    }

    function _roeOfDeal(
        uint32 dealPrice,
        uint32 issuePrice,
        uint48 closingDeadline,
        uint48 issueDateOfShare
    ) private pure returns (uint32 roe) {
        require(dealPrice > issuePrice, "ROE: NEGATIVE selling price");
        require(closingDeadline > issueDateOfShare, "ROE: NEGATIVE holding period");

        uint deltaPrice = uint(dealPrice - issuePrice);
        uint deltaDate = uint(closingDeadline - issueDateOfShare);

        roe = uint32(deltaPrice * 10000 / uint(issuePrice) * 31536000 / deltaDate);
    }
}