👮LOOKeeper
Keeper of Listing Orders
Name
LOOKeeper
Dependent Contract
ILOOKeeper, AccessControl, SharesRepo
API:
Source Code:
LOOKeeper
// 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 "../common/access/AccessControl.sol";
import "./ILOOKeeper.sol";
contract LOOKeeper is ILOOKeeper, AccessControl {
using RulesParser for bytes32;
//##################
//## Modifier ##
//##################
//###############
//## Write ##
//###############
function regInvestor(
uint caller,
uint groupRep,
bytes32 idHash
) external onlyDK {
IListOfOrders _loo = _gk.getLOO();
_loo.regInvestor(caller, groupRep, idHash);
}
function approveInvestor(
uint userNo,
uint caller,
uint seqOfLR
) external onlyDK {
IListOfOrders _loo = _gk.getLOO();
RulesParser.ListingRule memory lr =
_gk.getSHA().getRule(seqOfLR).listingRuleParser();
require(_gk.getROD().hasTitle(caller, lr.titleOfVerifier),
"LOOK.apprInv: no rights");
require(lr.maxQtyOfInvestors == 0 ||
_loo.getQtyOfInvestors() < lr.maxQtyOfInvestors,
"LOOK.apprInv: no quota");
_gk.getLOO().approveInvestor(userNo, caller);
}
function revokeInvestor(
uint userNo,
uint caller,
uint seqOfLR
) external onlyDK {
RulesParser.ListingRule memory lr =
_gk.getSHA().getRule(seqOfLR).listingRuleParser();
require(_gk.getROD().hasTitle(caller, lr.titleOfVerifier),
"LOOK.revokeInv: wrong titl");
_gk.getLOO().revokeInvestor(userNo, caller);
}
function placeInitialOffer(
uint caller,
uint classOfShare,
uint execHours,
uint paid,
uint price,
uint seqOfLR
) external onlyDK {
IRegisterOfShares _ros = _gk.getROS();
RulesParser.ListingRule memory lr =
_gk.getSHA().getRule(seqOfLR).listingRuleParser();
require(_gk.getROD().hasTitle(caller, lr.titleOfIssuer),
"LOOK.placeIO: not entitled");
require(lr.classOfShare == classOfShare,
"LOOK.placeIO: wrong class");
require(uint32(price) >= lr.floorPrice,
"LOOK.placeIO: lower than floor");
require(lr.ceilingPrice == 0 ||
uint32(price) <= lr.ceilingPrice,
"LOOK.placeIO: higher than ceiling");
require (_ros.getInfoOfClass(classOfShare).body.cleanPaid +
paid <= lr.maxTotalPar, "LOOK.placeIO: paid overflow");
_gk.getLOO().placeSellOrder(
classOfShare,
0,
lr.votingWeight,
paid,
price,
execHours,
true
);
_ros.increaseEquityOfClass(true, classOfShare, 0, 0, paid);
}
function withdrawInitialOffer(
uint caller,
uint classOfShare,
uint seqOfOrder,
uint seqOfLR
) external onlyDK {
IListOfOrders _loo = _gk.getLOO();
IRegisterOfShares _ros = _gk.getROS();
GoldChain.Node memory order =
_loo.getOrder(classOfShare, seqOfOrder);
require(order.seqOfShare == 0,
"LOOK.withdrawInitOrder: not initOrder");
RulesParser.ListingRule memory lr =
_gk.getSHA().getRule(seqOfLR).listingRuleParser();
require(_gk.getROD().hasTitle(caller, lr.titleOfIssuer),
"LOOK.withdrawInitOrder: has no title");
order = _loo.withdrawSellOrder(classOfShare, seqOfOrder);
_ros.increaseEquityOfClass(false, classOfShare, 0, 0, order.paid);
}
function placeSellOrder(
uint caller,
uint seqOfClass,
uint execHours,
uint paid,
uint price,
uint seqOfLR,
bool sortFromHead
) external onlyDK {
IRegisterOfShares _ros = _gk.getROS();
RulesParser.ListingRule memory lr =
_gk.getSHA().getRule(seqOfLR).listingRuleParser();
require(seqOfClass == lr.classOfShare,
"LOOK.placePut: wrong class");
require(uint32(price) >= lr.offPrice,
"LOOK.placePut: lower than offPrice");
uint[] memory sharesInhand =
_gk.getROM().sharesInClass(caller, lr.classOfShare);
uint len = sharesInhand.length;
while (len > 0 && paid > 0) {
SharesRepo.Share memory share =
_ros.getShare(sharesInhand[len - 1]);
len--;
if(lr.lockupDays == 0 ||
share.head.issueDate +
uint48(lr.lockupDays) * 86400 < block.timestamp)
{
if (share.body.cleanPaid > 0) {
if (paid >= share.body.cleanPaid) {
_createSellOrder(
share,
share.body.cleanPaid,
price,
execHours,
sortFromHead,
_ros
);
paid -=share.body.cleanPaid;
} else {
_createSellOrder(
share,
paid,
price,
execHours,
sortFromHead,
_ros
);
break;
}
}
}
}
}
function _createSellOrder(
SharesRepo.Share memory share,
uint paid,
uint price,
uint execHours,
bool sortFromHead,
IRegisterOfShares _ros
) private {
_ros.decreaseCleanPaid(share.head.seqOfShare, paid);
_gk.getLOO().placeSellOrder(
share.head.class,
share.head.seqOfShare,
share.head.votingWeight,
paid,
price,
execHours,
sortFromHead
);
}
function withdrawSellOrder(
uint caller,
uint classOfShare,
uint seqOfOrder
) external onlyDK {
IListOfOrders _loo = _gk.getLOO();
IRegisterOfShares _ros = _gk.getROS();
GoldChain.Node memory order =
_loo.getOrder(classOfShare, seqOfOrder);
require(order.seqOfShare > 0,
"LOOK.withdrawSellOrder: zero seqOfShare");
SharesRepo.Share memory share =
_ros.getShare(order.seqOfShare);
require(share.head.shareholder == caller,
"LOOK.withdrawSellOrder: not shareholder");
order = _loo.withdrawSellOrder(classOfShare, seqOfOrder);
_ros.increaseCleanPaid(order.seqOfShare, order.paid);
}
function placeBuyOrder(
uint caller,
uint classOfShare,
uint paid,
uint price,
uint msgValue
) external onlyDK {
IRegisterOfShares _ros = _gk.getROS();
IRegisterOfMembers _rom = _gk.getROM();
uint centPrice = _gk.getCentPrice();
require(paid * price * centPrice / 100 <= msgValue,
"LOOK.placeCall: insufficient value");
(OrdersRepo.Deal[] memory deals, GoldChain.Node[] memory expired) =
_gk.getLOO().placeBuyOrder(
caller,
classOfShare,
paid,
price
);
uint len = deals.length;
while (len > 0) {
OrdersRepo.Deal memory deal = deals[len - 1];
len--;
uint valueOfDeal = deal.paid * deal.price * centPrice / 100;
msgValue -= valueOfDeal;
if (deal.seqOfShare > 0) {
SharesRepo.Share memory share = _ros.getShare(deal.seqOfShare);
_gk.saveToCoffer(share.head.shareholder, valueOfDeal);
_ros.increaseCleanPaid(deal.seqOfShare, deal.paid);
_ros.transferShare(
deal.seqOfShare,
deal.paid,
deal.paid,
deal.buyer,
deal.price,
deal.price
);
} else {
SharesRepo.Share memory share;
share.head = SharesRepo.Head({
class: uint16(classOfShare),
seqOfShare: 0,
preSeq: 0,
issueDate: 0,
shareholder: deal.buyer,
priceOfPaid: deal.price,
priceOfPar: deal.price,
votingWeight: deal.votingWeight,
argu: 0
});
share.body = SharesRepo.Body({
payInDeadline: uint48(block.timestamp + 86400),
paid: deal.paid,
par: deal.paid,
cleanPaid: deal.paid,
state: 0,
para: 0
});
_ros.addShare(share);
}
if (deal.groupRep != deal.buyer &&
deal.groupRep != _rom.groupRep(deal.buyer))
_rom.addMemberToGroup(deal.buyer, deal.groupRep);
// _loo.removeDeals();
}
if (msgValue > 0)
_gk.saveToCoffer(caller, msgValue);
len = expired.length;
while (len > 0) {
GoldChain.Node memory offer = expired[len - 1];
len--;
if (offer.seqOfShare > 0)
_ros.increaseCleanPaid(offer.seqOfShare, offer.paid);
else
_ros.increaseEquityOfClass(false, classOfShare, 0, 0, offer.paid);
}
}
}
ILOOKeeper
// 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 "../../lib/SharesRepo.sol";
interface ILOOKeeper {
//##################
//## Modifier ##
//##################
//###############
//## Write ##
//###############
function regInvestor(
uint userNo,
uint groupRep,
bytes32 idHash
// uint seqOfLR
) external;
function approveInvestor(
uint userNo,
uint caller,
uint seqOfLR
) external;
function revokeInvestor(
uint userNo,
uint caller,
uint seqOfLR
) external;
function placeInitialOffer(
uint caller,
uint classOfShare,
uint execHours,
uint paid,
uint price,
uint seqOfLR
) external;
function withdrawInitialOffer(
uint caller,
uint classOfShare,
uint seqOfOrder,
uint seqOfLR
) external;
function placeSellOrder(
uint caller,
uint seqOfClass,
uint execHours,
uint paid,
uint price,
uint seqOfLR,
bool sortFromHead
) external;
function withdrawSellOrder(
uint caller,
uint classOfShare,
uint seqOfOrder
) external;
function placeBuyOrder(
uint caller,
uint classOfShare,
uint paid,
uint price,
uint msgValue
) external;
}