文件 1 的 15:Address.sol
pragma solidity ^0.6.2;
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 15:BytesLib.sol
pragma solidity ^0.6.0;
library BytesLib {
function concat(
bytes memory _preBytes,
bytes memory _postBytes
)
internal
pure
returns (bytes memory)
{
bytes memory tempBytes;
assembly {
tempBytes := mload(0x40)
let length := mload(_preBytes)
mstore(tempBytes, length)
let mc := add(tempBytes, 0x20)
let end := add(mc, length)
for {
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
mc := end
end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(0x40, and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31)
))
}
return tempBytes;
}
function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
assembly {
let fslot := sload(_preBytes_slot)
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
let mlength := mload(_postBytes)
let newlength := add(slength, mlength)
switch add(lt(slength, 32), lt(newlength, 32))
case 2 {
sstore(
_preBytes_slot,
add(
fslot,
add(
mul(
div(
mload(add(_postBytes, 0x20)),
exp(0x100, sub(32, mlength))
),
exp(0x100, sub(32, newlength))
),
mul(mlength, 2)
)
)
)
}
case 1 {
mstore(0x0, _preBytes_slot)
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
sstore(_preBytes_slot, add(mul(newlength, 2), 1))
let submod := sub(32, slength)
let mc := add(_postBytes, submod)
let end := add(_postBytes, mlength)
let mask := sub(exp(0x100, submod), 1)
sstore(
sc,
add(
and(
fslot,
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
),
and(mload(mc), mask)
)
)
for {
mc := add(mc, 0x20)
sc := add(sc, 1)
} lt(mc, end) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
sstore(sc, mload(mc))
}
mask := exp(0x100, sub(mc, end))
sstore(sc, mul(div(mload(mc), mask), mask))
}
default {
mstore(0x0, _preBytes_slot)
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
sstore(_preBytes_slot, add(mul(newlength, 2), 1))
let slengthmod := mod(slength, 32)
let mlengthmod := mod(mlength, 32)
let submod := sub(32, slengthmod)
let mc := add(_postBytes, submod)
let end := add(_postBytes, mlength)
let mask := sub(exp(0x100, submod), 1)
sstore(sc, add(sload(sc), and(mload(mc), mask)))
for {
sc := add(sc, 1)
mc := add(mc, 0x20)
} lt(mc, end) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
sstore(sc, mload(mc))
}
mask := exp(0x100, sub(mc, end))
sstore(sc, mul(div(mload(mc), mask), mask))
}
}
}
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
)
internal
pure
returns (bytes memory)
{
require(_bytes.length >= (_start + _length), "Read out of bounds");
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
tempBytes := mload(0x40)
let lengthmod := and(_length, 31)
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for {
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
mstore(0x40, and(add(mc, 31), not(31)))
}
default {
tempBytes := mload(0x40)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
require(_bytes.length >= (_start + 20), "Read out of bounds");
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
}
return tempAddress;
}
function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
require(_bytes.length >= (_start + 1), "Read out of bounds");
uint8 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x1), _start))
}
return tempUint;
}
function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
require(_bytes.length >= (_start + 2), "Read out of bounds");
uint16 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x2), _start))
}
return tempUint;
}
function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
require(_bytes.length >= (_start + 4), "Read out of bounds");
uint32 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x4), _start))
}
return tempUint;
}
function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
require(_bytes.length >= (_start + 8), "Read out of bounds");
uint64 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x8), _start))
}
return tempUint;
}
function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
require(_bytes.length >= (_start + 12), "Read out of bounds");
uint96 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0xc), _start))
}
return tempUint;
}
function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
require(_bytes.length >= (_start + 16), "Read out of bounds");
uint128 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x10), _start))
}
return tempUint;
}
function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
require(_bytes.length >= (_start + 32), "Read out of bounds");
uint256 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x20), _start))
}
return tempUint;
}
function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
require(_bytes.length >= (_start + 32), "Read out of bounds");
bytes32 tempBytes32;
assembly {
tempBytes32 := mload(add(add(_bytes, 0x20), _start))
}
return tempBytes32;
}
function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
bool success = true;
assembly {
let length := mload(_preBytes)
switch eq(length, mload(_postBytes))
case 1 {
let cb := 1
let mc := add(_preBytes, 0x20)
let end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} eq(add(lt(mc, end), cb), 2) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
if iszero(eq(mload(mc), mload(cc))) {
success := 0
cb := 0
}
}
}
default {
success := 0
}
}
return success;
}
function equalStorage(
bytes storage _preBytes,
bytes memory _postBytes
)
internal
view
returns (bool)
{
bool success = true;
assembly {
let fslot := sload(_preBytes_slot)
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
let mlength := mload(_postBytes)
switch eq(slength, mlength)
case 1 {
if iszero(iszero(slength)) {
switch lt(slength, 32)
case 1 {
fslot := mul(div(fslot, 0x100), 0x100)
if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
success := 0
}
}
default {
let cb := 1
mstore(0x0, _preBytes_slot)
let sc := keccak256(0x0, 0x20)
let mc := add(_postBytes, 0x20)
let end := add(mc, mlength)
for {} eq(add(lt(mc, end), cb), 2) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
if iszero(eq(sload(sc), mload(mc))) {
success := 0
cb := 0
}
}
}
}
}
default {
success := 0
}
}
return success;
}
}
文件 3 的 15:Common.sol
pragma solidity >=0.6.0;
contract Common {
bytes32 internal EMPTY_BYTES32;
uint256 internal constant PERCENT_BASE = 1000;
uint256 internal constant ROOT_ID = 6666;
uint256 internal constant MAX_LEVEL_DEEP = 7;
uint256 internal constant BLOCK_PER_ROUND = 5760;
uint256 internal constant DELAY_ROUND = 10;
uint256 internal constant ROUND_ALLOW_PREORDER = 15;
uint256 internal constant NEWBIE_BLOCKS = 160;
uint256 internal constant ROUND_PREORDER_LIMIT_PERCENT = 700;
string constant ERROR_HELPING_FUND_NOT_ENOUGH = "1";
string constant ERROR_DEFI_IS_BANKRUPT = "2";
string constant ERROR_ACCOUNT_IS_DISABLED = "3";
string constant ERROR_UNINVESTABLE = "4";
string constant ERROR_INVALID_STATUS = "5";
string constant ERROR_INVALID_INVITE_CODE = "6";
string constant ERROR_REFERRER_NOT_FOUND = "7";
string constant ERROR_USER_ALREADY_REGISTED = "8";
string constant ERROR_USER_IS_NOT_REGISTED = "9";
string constant ERROR_USER_HAS_NOT_INVESTED = "10";
string constant ERROR_ROUND_IS_NOT_OVER = "11";
string constant ERROR_TRY_AGAIN_IN_A_DAY = "12";
string constant ERROR_USER_ACTIVATED = "13";
string constant ERROR_USER_IS_NOT_ACTIVATED = "14";
string constant ERROR_USER_INVESTED = "15";
string constant ERROR_INVESTMENT_GEAR_IS_INCORRECT = "16";
string constant ERROR_USER_IS_NOT_NODE = "17";
string constant ERROR_USER_IS_NOT_SUPER_NODE = "18";
string constant ERROR_NO_MORE_BONUS = "19";
string constant ERROR_ALREADY_CLAIMED = "20";
string constant ERROR_NOT_IN_LAST100 = "21";
string constant ERROR_NO_ORIGINAL_ACCOUNT_QUOTA = "22";
string constant ERROR_ETH_NOT_ENOUGH = "23";
string constant ERROR_TOKEN_NOT_ENOUGH = "24";
string constant ERROR_UNMATCHED_PAYMENT_ACTION = "25";
enum EventAction {
Unknown,
PurchaseOriginalAccount,
UserActive,
UserInvestment,
ReferralUserInvestment,
ClaimROI,
ClaimCompensation,
ClaimNodeBonus,
ClaimSuperNodeBonus,
ClaimLast100Bonus
}
event UserRegister(
uint256 indexed eventID,
uint256 indexed userID,
uint256 blockNumber,
uint256 referralUserID,
address userAddr
);
event UserActive(
uint256 indexed eventID,
uint256 indexed userID,
uint256 blockNumber,
uint256[MAX_LEVEL_DEEP + 1] referrers,
uint256[MAX_LEVEL_DEEP + 1] tokenAmts,
uint256[MAX_LEVEL_DEEP + 1] usdAmts,
bytes32 inviteCode
);
event Billing(
uint256 indexed eventID,
uint256 indexed userID,
uint256 blockNumber,
EventAction action,
uint256 extData,
uint256 extData1,
uint256 extData2,
uint256 tokenAmt,
uint256 usdAmt,
uint256 feeUSD
);
event UserData(
uint256 indexed eventID,
uint256 indexed userID,
uint256 blockNumber,
EventAction action,
uint256 fromUserID,
uint256 extData,
bool[2] userBoolArray,
uint256[21] userUint256Array
);
event RoundData(
uint256 indexed eventID,
uint256 indexed roundID,
uint256 blockNumber,
uint256[4] roundUint256Vars
);
}
文件 4 的 15:DeFiCommon.sol
pragma solidity >=0.6.0;
import "./Common.sol";
contract DeFiCommon is Common {
event Error(string reason, uint256 extData, uint256 blockNumber);
}
文件 5 的 15:DeFiLogic.sol
pragma solidity >=0.6.0;
import "./IDeFi.sol";
import "./IDeFiLogic.sol";
import "./ILast100Logic.sol";
import "./IDeFiStorage.sol";
import "./IGlobalLogic.sol";
import "./IUpgradable.sol";
import "./Common.sol";
import "./DeFiCommon.sol";
import "./SafeMath.sol";
import "./SafeERC20.sol";
import "./BytesLib.sol";
contract DeFiLogic is Common, DeFiCommon, IUpgradable, IDeFiLogic {
using SafeERC20 for IERC20;
using SafeMath for uint256;
using BytesLib for bytes;
uint256 private constant ACTIVE_FEE = 5e5;
uint256 private constant ACTION_ACTIVE = 1001;
uint256 private constant AVAILABLE_BRING_OUT_PERCENT = 500;
uint256 private constant OriginalAccountPrice = 1e18;
uint256 private constant OriginalAccountPriceGrow = 1e17;
uint256 private constant OriginalAccountNewOpenQuota = 10;
uint256 private constant OriginalAccountNewOpenQuotaDelayDays = 30;
IDeFiStorage _fs;
IGlobalLogic _gl;
IDeFi _df;
mapping(uint256 => uint256) private _quotas;
modifier ensureStatus(IDeFiStorage.GlobalStatus requireStatus) {
IDeFiStorage.GlobalStatus status = _fs.getGlobalStatus();
require(
status == requireStatus ||
(requireStatus == IDeFiStorage.GlobalStatus.Pending &&
(status == IDeFiStorage.GlobalStatus.Pending ||
status == IDeFiStorage.GlobalStatus.Started)),
ERROR_INVALID_STATUS
);
_;
}
function onTokenReceived(
address token,
address,
address msgSender,
address,
uint256 amount,
bytes memory userData,
bytes memory
) public override onlyInternal {
assert(token == _fs.getToken());
if (msgSender == address(0)) return;
uint256 userDataUint256;
if (userData.length > 0) {
userDataUint256 = userData.toUint256(0);
}
uint256 usdAmt = _fs.T2U(amount);
if (ACTION_ACTIVE == userDataUint256) {
assert(usdAmt == ACTIVE_FEE);
activation(msgSender, amount, usdAmt);
return;
} else if (userDataUint256 > 0) {
uint256 gear = _fs.getInvestGear(usdAmt);
if (gear > 0) {
invest(msgSender, userDataUint256, amount, usdAmt, gear);
return;
}
revert(ERROR_UNMATCHED_PAYMENT_ACTION);
}
}
function getOriginalAccountQuota()
public
override
view
returns (
uint256,
uint256,
uint256
)
{
uint256[3] memory globalBlocks = _fs.getGlobalBlocks();
uint256 rounds = block.number <= globalBlocks[0]
? 0
: block.number.sub(globalBlocks[0]).div(
BLOCK_PER_ROUND * OriginalAccountNewOpenQuotaDelayDays
);
return (
OriginalAccountPrice.add(rounds.mul(OriginalAccountPriceGrow)),
OriginalAccountNewOpenQuota > _quotas[rounds]
? OriginalAccountNewOpenQuota.sub(_quotas[rounds])
: 0,
rounds
);
}
function register(
address msgSender,
uint256 msgValue,
bytes32 inviteCode,
bool purchaseOriginAccount
)
public
override
onlyInternal
ensureStatus(IDeFiStorage.GlobalStatus.Pending)
{
require(_fs.getIDByAddr(msgSender) == 0, ERROR_USER_ALREADY_REGISTED);
uint256 userID = _fs.issueUserID(msgSender);
uint256[21] memory userUint256Array;
if (!purchaseOriginAccount) {
require(inviteCode != EMPTY_BYTES32, ERROR_INVALID_INVITE_CODE);
uint256 fatherID = _fs.getIDByInviteCode(inviteCode);
require(fatherID != 0, ERROR_REFERRER_NOT_FOUND);
bool[2] memory userBoolArray;
userUint256Array[1] = fatherID;
_fs.setUser(userID, userBoolArray, userUint256Array);
emit UserRegister(
_fs.issueEventIndex(),
userID,
block.number,
fatherID,
msgSender
);
} else {
(
uint256 price,
uint256 quota,
uint256 rounds
) = getOriginalAccountQuota();
require(quota > 0, ERROR_NO_ORIGINAL_ACCOUNT_QUOTA);
_quotas[rounds]++;
require(price <= msgValue, ERROR_ETH_NOT_ENOUGH);
userUint256Array[1] = ROOT_ID;
emit UserRegister(
_fs.issueEventIndex(),
userID,
block.number,
ROOT_ID,
msgSender
);
uint256 _stackTooDeep_msgValue = msgValue;
emit Billing(
_fs.issueEventIndex(),
userID,
block.number,
EventAction.PurchaseOriginalAccount,
0,
0,
0,
0,
_stackTooDeep_msgValue,
0
);
_df.sendETH(_fs.getPlatformAddress(), _stackTooDeep_msgValue);
}
bytes32 newInviteCode = _gl.generateInviteCode(userID);
_fs.setUserInviteCode(userID, newInviteCode);
userUint256Array[0]++;
bool[2] memory userBoolArray;
_fs.setUser(userID, userBoolArray, userUint256Array);
uint256[MAX_LEVEL_DEEP + 1] memory empty;
emit UserActive(
_fs.issueEventIndex(),
userID,
block.number,
empty,
empty,
empty,
newInviteCode
);
}
function claimROI(address msgSender)
public
override
onlyInternal
ensureStatus(IDeFiStorage.GlobalStatus.Started)
{
_gl.internalSplitPool();
uint256 userID = _fs.getIDByAddr(msgSender);
require(userID > 0, ERROR_USER_IS_NOT_REGISTED);
(
bool[2] memory userBoolArray,
uint256[21] memory userUint256Array
) = _fs.getUser(userID);
require(userUint256Array[6] > 0, ERROR_USER_HAS_NOT_INVESTED);
require(
block.number.sub(BLOCK_PER_ROUND * DELAY_ROUND) >
userUint256Array[6],
ERROR_ROUND_IS_NOT_OVER
);
if (
userUint256Array[5] > 0 &&
userUint256Array[5].add(BLOCK_PER_ROUND) > block.number
) revert(ERROR_TRY_AGAIN_IN_A_DAY);
uint256 income = _fs.getLevelConfig(
userUint256Array[3],
IDeFiStorage.ConfigType.StaticIncomeAmt
);
income = income.add(userUint256Array[7]);
uint256 allAmt = income.add(
_fs.getLevelConfig(
userUint256Array[3],
IDeFiStorage.ConfigType.InvestAmt
)
);
uint256 allToken = _fs.U2T(allAmt);
uint256 distPool;
uint256[5] memory pools = _fs.getDeFiAccounts();
if (pools[distPool] < allToken) {
if (userUint256Array[4] >= 3) distPool = 1;
else if (userUint256Array[5].add(BLOCK_PER_ROUND) <= block.number) {
userUint256Array[4]++;
userUint256Array[5] = block.number;
_fs.setUser(userID, userBoolArray, userUint256Array);
emit Error(
ERROR_HELPING_FUND_NOT_ENOUGH,
userUint256Array[4],
block.number
);
return;
}
}
if (pools[distPool] < allToken) {
uint256[3] memory globalBlocks = _fs.getGlobalBlocks();
globalBlocks[1] = block.number;
_fs.setGlobalBlocks(globalBlocks);
emit Error(ERROR_DEFI_IS_BANKRUPT, globalBlocks[1], block.number);
return;
}
uint256 fee = allAmt.per(
PERCENT_BASE,
_fs.getLevelConfig(
userUint256Array[3],
IDeFiStorage.ConfigType.ClaimFeePercent
)
);
uint256 distAmt = allAmt.sub(fee);
uint256 distTokenAmt = _fs.U2T(distAmt);
pools[distPool] = pools[distPool].sub(allToken);
_df.sendToken(_fs.getPlatformAddress(), allToken.sub(distTokenAmt));
_fs.setDeFiAccounts(pools);
address _stackTooDeep_msgSender = msgSender;
uint256 _stackTooDeep_userID2 = userID;
(
uint256 investGear,
uint256 roundBringOut,
uint256 roundID
) = _clearUserInvestmentInfo(userUint256Array, income);
bool[2] memory _stackTooDeep_userBoolArray2 = userBoolArray;
uint256[21] memory _stackTooDeep_userUint256Array2 = userUint256Array;
uint256 _stackTooDeep_distTokenAmt = distTokenAmt;
uint256 _stackTooDeep_distAmt = distAmt;
_fs.setUser(
_stackTooDeep_userID2,
_stackTooDeep_userBoolArray2,
_stackTooDeep_userUint256Array2
);
_df.sendToken(_stackTooDeep_msgSender, _stackTooDeep_distTokenAmt);
uint256 _stackTooDeep_fee = fee;
emit Billing(
_fs.issueEventIndex(),
_stackTooDeep_userID2,
block.number,
EventAction.ClaimROI,
roundID,
investGear,
roundBringOut,
_stackTooDeep_distTokenAmt,
_stackTooDeep_distAmt,
_stackTooDeep_fee
);
emit UserData(
_fs.issueEventIndex(),
_stackTooDeep_userID2,
block.number,
EventAction.ClaimROI,
_stackTooDeep_userID2,
0,
_stackTooDeep_userBoolArray2,
_stackTooDeep_userUint256Array2
);
}
function deposit(
address,
uint256 poolID,
uint256 tokenAmt
) public override onlyInternal {
uint256[5] memory pools = _fs.getDeFiAccounts();
pools[poolID] = pools[poolID].add(tokenAmt);
_fs.setDeFiAccounts(pools);
}
function activation(
address msgSender,
uint256 tokenAmt,
uint256 usdAmt
) private ensureStatus(IDeFiStorage.GlobalStatus.Pending) {
uint256 userID = _fs.getIDByAddr(msgSender);
require(userID > 0, ERROR_USER_IS_NOT_REGISTED);
require(
_fs.getInviteCodeByID(userID) == EMPTY_BYTES32,
ERROR_USER_ACTIVATED
);
bytes32 inviteCode = _gl.generateInviteCode(userID);
_fs.setUserInviteCode(userID, inviteCode);
(
bool[2] memory userBoolArray,
uint256[21] memory userUint256Array
) = _fs.getUser(userID);
userUint256Array[0]++;
_fs.setUser(userID, userBoolArray, userUint256Array);
emit Billing(
_fs.issueEventIndex(),
userID,
block.number,
EventAction.UserActive,
0,
0,
0,
tokenAmt,
usdAmt,
0
);
uint256 balance = tokenAmt;
uint256 usdBalance = ACTIVE_FEE;
uint256 splitedAmt = tokenAmt.div(10);
uint256 splitedUsdAmt = usdBalance.div(10);
uint256[MAX_LEVEL_DEEP] memory fathers = _fs.getUserFatherIDs(userID);
address[MAX_LEVEL_DEEP] memory fatherAddrs = _fs.getUserFatherAddrs(
userID
);
uint256[MAX_LEVEL_DEEP + 1] memory referrers;
uint256[MAX_LEVEL_DEEP + 1] memory usdAmts;
uint256[MAX_LEVEL_DEEP + 1] memory tokenAmts;
bool isBreak;
for (uint256 i = 0; i <= MAX_LEVEL_DEEP && !isBreak; i++) {
referrers[i] = (i == MAX_LEVEL_DEEP || fathers[i] == 0)
? ROOT_ID
: fathers[i];
if (referrers[i] == ROOT_ID) {
usdAmts[i] = usdBalance;
tokenAmts[i] = balance;
isBreak = true;
} else if (i == 0) {
tokenAmts[i] = splitedAmt.mul(3);
usdAmts[i] = splitedUsdAmt.mul(3);
} else {
tokenAmts[i] = splitedAmt;
usdAmts[i] = splitedUsdAmt;
}
if (
referrers[i] != ROOT_ID &&
i != MAX_LEVEL_DEEP &&
fatherAddrs[i] == address(0)
) {
continue;
}
balance = balance.sub(tokenAmts[i]);
usdBalance = usdBalance.sub(usdAmts[i]);
_df.sendToken(
referrers[i] == ROOT_ID
? _fs.getPlatformAddress()
: fatherAddrs[i],
tokenAmts[i]
);
}
bytes32 _stackTooDeep_inviteCode2 = inviteCode;
emit UserActive(
_fs.issueEventIndex(),
userID,
block.number,
referrers,
tokenAmts,
usdAmts,
_stackTooDeep_inviteCode2
);
}
function invest(
address msgSender,
uint256 roundID,
uint256 tokenAmt,
uint256 usdAmt,
uint256 gear
) private ensureStatus(IDeFiStorage.GlobalStatus.Started) {
uint256 userID = _fs.getIDByAddr(msgSender);
require(userID > 0, ERROR_USER_IS_NOT_REGISTED);
require(
userID == ROOT_ID || _fs.getInviteCodeByID(userID) != EMPTY_BYTES32,
ERROR_USER_IS_NOT_ACTIVATED
);
_gl.checkDeactiveReferrals(userID);
(
bool[2] memory userBoolArray,
uint256[21] memory userUint256Array
) = _fs.getUser(userID);
require(userUint256Array[6] == 0, ERROR_USER_INVESTED);
require(
userUint256Array[0] >= gear && userUint256Array[3] <= gear,
ERROR_INVESTMENT_GEAR_IS_INCORRECT
);
bool isNewUser = userUint256Array[3] == 0;
if (
!_gl.checkUserAlive(
userID,
userUint256Array[6],
userUint256Array[2],
msgSender
)
) {
emit Error(ERROR_ACCOUNT_IS_DISABLED, userID, block.number);
_df.sendToken(msgSender, tokenAmt);
return;
}
updateUserInfo(
userID,
userUint256Array,
isNewUser,
roundID,
gear,
tokenAmt,
usdAmt
);
_fs.setUser(userID, userBoolArray, userUint256Array);
uint256[5] memory selfInvestCount;
if (gear <= userUint256Array[0] && userUint256Array[0] < 5) {
selfInvestCount = _fs.getSelfInvestCount(userID);
selfInvestCount[gear - 1] = selfInvestCount[gear - 1].add(1);
_fs.setSelfInvestCount(userID, selfInvestCount);
}
if (userID != ROOT_ID) _fs.pushToInvestQueue(userID);
_fs.effectReferrals(userID, roundID, usdAmt, isNewUser);
}
function updateUserInfo(
uint256 userID,
uint256[21] memory userUint256Array,
bool isNewUser,
uint256 roundID,
uint256 gear,
uint256 tokenAmt,
uint256 usdAmt
) private {
if (
!_fs.checkRoundAvailableAndUpdate(
isNewUser,
roundID,
usdAmt,
tokenAmt
)
) revert(ERROR_UNINVESTABLE);
userUint256Array[2] = block.number;
userUint256Array[3] = gear;
userUint256Array[6] = roundID;
userUint256Array[9] = userUint256Array[9].add(usdAmt);
userUint256Array[7] = usdAmt.per(
PERCENT_BASE,
AVAILABLE_BRING_OUT_PERCENT
);
if (userUint256Array[7] > userUint256Array[8]) {
userUint256Array[7] = userUint256Array[8];
}
userUint256Array[7] = userUint256Array[7].div(1e6).mul(1e6);
emit Billing(
_fs.issueEventIndex(),
userID,
block.number,
EventAction.UserInvestment,
roundID,
userUint256Array[3],
userUint256Array[7],
tokenAmt,
usdAmt,
0
);
}
function _clearUserInvestmentInfo(
uint256[21] memory userUint256Array,
uint256 income
)
private
view
returns (
uint256 investGear,
uint256 roundBringOut,
uint256 roundID
)
{
investGear = userUint256Array[3];
roundBringOut = userUint256Array[7];
userUint256Array[2] = block.number;
userUint256Array[4] = 0;
userUint256Array[5] = 0;
roundID = userUint256Array[6];
userUint256Array[6] = 0;
userUint256Array[8] = userUint256Array[8].sub(userUint256Array[7]);
userUint256Array[7] = 0;
userUint256Array[16] = userUint256Array[16].add(income);
}
function changeDependentContractAddress() public override {
_gl = IGlobalLogic(master.getLatestAddress("GL"));
_fs = IDeFiStorage(master.getLatestAddress("FS"));
_df = IDeFi(master.getLatestAddress("DF"));
}
}
文件 6 的 15:IDeFi.sol
pragma solidity >=0.6.0;
interface IDeFi {
function sendToken(address to, uint256 amt) external;
function sendETH(address payable to, uint256 amt) external;
}
文件 7 的 15:IDeFiLogic.sol
pragma solidity >=0.6.0;
interface IDeFiLogic {
function onTokenReceived(
address token,
address operator,
address msgSender,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external;
function getOriginalAccountQuota()
external
view
returns (
uint256,
uint256,
uint256
);
function register(
address msgSender,
uint256 msgValue,
bytes32 inviteCode,
bool purchaseOriginAccount
) external;
function claimROI(address msgSender) external;
function deposit(
address msgSender,
uint256 poolID,
uint256 tokenAmt
) external;
}
文件 8 的 15:IDeFiStorage.sol
pragma solidity >=0.6.0;
interface IDeFiStorage {
enum ConfigType {
InvestAmt,
StaticIncomeAmt,
DynamicIncomePercent,
ClaimFeePercent,
UpgradeRequiredInviteValidPlayerCount,
UpgradeRequiredMarketPerformance,
UpgradeRequiredSelfInvestCount
}
enum InvestType {Newbie, Open, PreOrder}
enum GlobalStatus {Pending, Started, Bankruptcy, Ended}
event GlobalBlocks(uint256 indexed eventID, uint256[3] blocks);
function getCurrentRoundID(bool enableCurrentBlock)
external
view
returns (uint256);
function getAvailableRoundID(bool isNewUser, bool enableCurrentBlock)
external
view
returns (uint256 id, InvestType investType);
function getInvestGear(uint256 usdAmt) external view returns (uint256);
function U2T(uint256 usdAmt) external view returns (uint256);
function U2E(uint256 usdAmt) external view returns (uint256);
function T2U(uint256 tokenAmt) external view returns (uint256);
function E2U(uint256 etherAmt) external view returns (uint256);
function T2E(uint256 tokenAmt) external view returns (uint256);
function E2T(uint256 etherAmt) external view returns (uint256);
function getGlobalStatus() external view returns (GlobalStatus);
function last100() external view returns (uint256[100] memory);
function getGlobalBlocks() external view returns (uint256[3] memory);
function getDeFiAccounts() external view returns (uint256[5] memory);
function getPoolSplitStats() external view returns (uint256[3] memory);
function getPoolSplitPercent(uint256 roundID) external view returns (uint256[6] memory splitPrcent, uint256[2] memory nodeCount);
function isLast100AndLabel(uint256 userID) external returns (bool);
function increaseRoundData(
uint256 roundID,
uint256 dataID,
uint256 num
) external;
function getNodePerformance(
uint256 roundID,
uint256 nodeID,
bool isSuperNode
) external view returns (uint256);
function increaseUserData(
uint256 userID,
uint256 dataID,
uint256 num,
bool isSub,
bool isSet
) external;
function checkRoundAvailableAndUpdate(
bool isNewUser,
uint256 roundID,
uint256 usdAmt,
uint256 tokenAmt
) external returns (bool success);
function increaseDeFiAccount(
uint256 accountID,
uint256 num,
bool isSub
) external returns (bool);
function getUser(uint256 userID)
external
view
returns (
bool[2] memory userBoolArray,
uint256[21] memory userUint256Array
);
function getUserUint256Data(uint256 userID, uint256 dataID)
external
view
returns (uint256);
function setDeFiAccounts(uint256[5] calldata data) external;
function splitDone() external;
function getSelfInvestCount(uint256 userID)
external
view
returns (uint256[5] memory selfInvestCount);
function setSelfInvestCount(
uint256 userID,
uint256[5] calldata selfInvestCount
) external;
function pushToInvestQueue(uint256 userID) external;
function effectReferrals(
uint256 userID,
uint256 roundID,
uint256 usdAmt,
bool isNewUser
) external;
function getLevelConfig(uint256 level, ConfigType configType)
external
view
returns (uint256);
function getUserFatherIDs(uint256 userID)
external
view
returns (uint256[7] memory fathers);
function getUserFatherActiveInfo(uint256 userID)
external
view
returns (
uint256[7] memory fathers,
uint256[7] memory roundID,
uint256[7] memory lastActive,
address[7] memory addrs
);
function getUserFatherAddrs(uint256 userID)
external
view
returns (address[7] memory fathers);
function setGlobalBlocks(uint256[3] calldata blocks) external;
function getGlobalNodeCount(uint256 roundID)
external
view
returns (uint256[2] memory nodeCount);
function getToken() external view returns (address);
function setToken(address token) external;
function getPlatformAddress() external view returns (address payable);
function setPlatformAddress(address payable platformAddress) external;
function getIDByAddr(address addr) external view returns (uint256);
function getAddrByID(uint256 id) external view returns (address);
function setUserAddr(uint256 id, address addr) external;
function getIDByInviteCode(bytes32 inviteCode)
external
view
returns (uint256);
function getInviteCodeByID(uint256 id) external view returns (bytes32);
function setUserInviteCode(uint256 id, bytes32 inviteCode) external;
function issueUserID(address addr) external returns (uint256);
function issueEventIndex() external returns (uint256);
function setUser(
uint256 userID,
bool[2] calldata userBoolArry,
uint256[21] calldata userUint256Array
) external;
function deactivateUser(uint256 id) external;
function getRound(uint256 roundID)
external
view
returns (uint256[4] memory roundUint256Vars);
function setRound(uint256 roundID, uint256[4] calldata roundUint256Vars)
external;
function setE2U(uint256 e2u) external;
function setT2U(uint256 t2u) external;
function setRoundLimit(uint256[] calldata roundID, uint256[] calldata limit)
external;
}
文件 9 的 15:IERC20.sol
pragma solidity ^0.6.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 10 的 15:IGlobalLogic.sol
pragma solidity >=0.6.0;
interface IGlobalLogic {
function checkUserAlive(
uint256 userID,
uint256 roundID,
uint256 lastActiveBlock,
address userAddr
) external returns (bool);
function checkDeactiveReferrals(uint256 userID) external;
function generateInviteCode(uint256 id) external view returns (bytes32);
function internalSplitPool() external;
}
文件 11 的 15:ILast100Logic.sol
pragma solidity >=0.6.0;
interface ILast100Logic {
function checkUserAvailable(address payable from)
external
returns (uint256);
function internalExchange() external;
}
文件 12 的 15:IMaster.sol
pragma solidity >=0.6.0;
interface IMaster {
function isOwner(address _addr) external view returns (bool);
function payableOwner() external view returns (address payable);
function isInternal(address _addr) external view returns (bool);
function getLatestAddress(bytes2 _contractName)
external
view
returns (address contractAddress);
}
文件 13 的 15:IUpgradable.sol
pragma solidity >=0.6.0;
import "./IMaster.sol";
import "./Address.sol";
abstract contract IUpgradable {
IMaster public master;
modifier onlyInternal {
assert(master.isInternal(msg.sender));
_;
}
modifier onlyOwner {
assert(master.isOwner(msg.sender));
_;
}
modifier onlyMaster {
assert(address(master) == msg.sender);
_;
}
function changeDependentContractAddress() public virtual;
function changeMasterAddress(address addr) public {
assert(Address.isContract(addr));
assert(address(master) == address(0) || address(master) == msg.sender);
master = IMaster(addr);
}
}
文件 14 的 15:SafeERC20.sol
pragma solidity ^0.6.0;
import "./IERC20.sol";
import "./SafeMath.sol";
import "./Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 15 的 15:SafeMath.sol
pragma solidity ^0.6.0;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
function per(uint256 a, uint256 base, uint256 percent) internal pure returns (uint256) {
return div(mul(a,percent),base);
}
}
{
"compilationTarget": {
"localhost/DeFiLogic.sol": "DeFiLogic"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eventID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"userID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"enum Common.EventAction","name":"action","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"extData","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extData1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extData2","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeUSD","type":"uint256"}],"name":"Billing","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"reason","type":"string"},{"indexed":false,"internalType":"uint256","name":"extData","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"Error","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eventID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"roundID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256[4]","name":"roundUint256Vars","type":"uint256[4]"}],"name":"RoundData","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eventID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"userID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256[8]","name":"referrers","type":"uint256[8]"},{"indexed":false,"internalType":"uint256[8]","name":"tokenAmts","type":"uint256[8]"},{"indexed":false,"internalType":"uint256[8]","name":"usdAmts","type":"uint256[8]"},{"indexed":false,"internalType":"bytes32","name":"inviteCode","type":"bytes32"}],"name":"UserActive","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eventID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"userID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"enum Common.EventAction","name":"action","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"fromUserID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extData","type":"uint256"},{"indexed":false,"internalType":"bool[2]","name":"userBoolArray","type":"bool[2]"},{"indexed":false,"internalType":"uint256[21]","name":"userUint256Array","type":"uint256[21]"}],"name":"UserData","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eventID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"userID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"referralUserID","type":"uint256"},{"indexed":false,"internalType":"address","name":"userAddr","type":"address"}],"name":"UserRegister","type":"event"},{"inputs":[],"name":"changeDependentContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"changeMasterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"name":"claimROI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"poolID","type":"uint256"},{"internalType":"uint256","name":"tokenAmt","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getOriginalAccountQuota","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"master","outputs":[{"internalType":"contract IMaster","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onTokenReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"uint256","name":"msgValue","type":"uint256"},{"internalType":"bytes32","name":"inviteCode","type":"bytes32"},{"internalType":"bool","name":"purchaseOriginAccount","type":"bool"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"}]