Blockwell

Valor Prime Non-Fungible Tokens

About

Stats

Public Functions 19
Event Types 6
Code Size 52,946 bytes

Library Use

Uses SafeMathUpgradeable for uint256.

Events (6) keyboard_arrow_up

MakePayout Event

Parameters help
value
uint256 help
sharesTotalSupply
uint256 help
time
uint256 help

RoleAdminChanged Event

Parameters help
role
bytes32 help
previousAdminRole
bytes32 help
newAdminRole
bytes32 help

RoleGranted Event

Parameters help
role
bytes32 help
account
address help
sender
address help

RoleRevoked Event

Parameters help
role
bytes32 help
account
address help
sender
address help

Stake Event

Parameters help
account
address help
sessionId
uint256 help
amount
uint256 help
start
uint256 help
end
uint256 help
shares
uint256 help

Unstake Event

Parameters help
account
address help
sessionId
uint256 help
amount
uint256 help
start
uint256 help
end
uint256 help
shares
uint256 help

Payout Struct

Members
payout
uint256 help
sharesTotalSupply
uint256 help

Session Struct

Members
amount
uint256 help
start
uint256 help
end
uint256 help
shares
uint256 help
firstPayout
uint256 help
lastPayout
uint256 help
withdrawn
bool help
payout
uint256 help

Addresses Struct

Members
mainToken
address help
auction
address help
subBalances
address help

MIGRATOR_ROLE Constant

bytes32 help

EXTERNAL_STAKER_ROLE Constant

bytes32 help

MANAGER_ROLE Constant

bytes32 help

DEFAULT_ADMIN_ROLE Constant

bytes32 help
0x00

addresses Variable

Addresses help

stakingV1 Variable

address help

shareRate Variable

uint256 help

sharesTotalSupply Variable

uint256 help

nextPayoutCall Variable

uint256 help

stepTimestamp Variable

uint256 help

startContract Variable

uint256 help

globalPayout Variable

uint256 help

globalPayin Variable

uint256 help

lastSessionId Variable

uint256 help

lastSessionIdV1 Variable

uint256 help

init_ Variable

bool help

sessionDataOf Variable

mapping(address => mapping(uint256 => Session)) help
Internal Variable

sessionsOf Variable

mapping(address => uint256[]) help
Internal Variable

payouts Variable

Payout[] help
Internal Variable

_initialized Variable

bool help
Internal Variable

_initializing Variable

bool help
Internal Variable

_roles Variable

mapping(bytes32 => RoleData) help
Internal Variable

__gap Variable

uint256[] help
Internal Variable

__gap Variable

uint256[] help
Internal Variable

Functions Expand All Collapse All

hasRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help public
Mutability help view
Source Code
function hasRole(bytes32 role, address account) public view returns (bool) {
  return _roles[role].members.contains(account);
}

getRoleMemberCount keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help

Properties

Visibility help public
Mutability help view
Source Code
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
  return _roles[role].members.length();
}

getRoleMember keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
index
uint256 help

Properties

Visibility help public
Mutability help view
Source Code
function getRoleMember(bytes32 role, uint256 index)
  public
  view
  returns (address)
{
  return _roles[role].members.at(index);
}

getRoleAdmin keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help

Properties

Visibility help public
Mutability help view
Source Code
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
  return _roles[role].adminRole;
}

grantRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help public
Mutability help transaction

Requirements help

null
Source Code
function grantRole(bytes32 role, address account) public virtual {
  require(
    hasRole(_roles[role].adminRole, _msgSender()),
    "AccessControl: sender must be an admin to grant"
  );

  _grantRole(role, account);
}

revokeRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help public
Mutability help transaction

Requirements help

null
Source Code
function revokeRole(bytes32 role, address account) public virtual {
  require(
    hasRole(_roles[role].adminRole, _msgSender()),
    "AccessControl: sender must be an admin to revoke"
  );

  _revokeRole(role, account);
}

renounceRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help public
Mutability help transaction

Requirements help

Source Code
function renounceRole(bytes32 role, address account) public virtual {
  require(
    account == _msgSender(),
    "AccessControl: can only renounce roles for self"
  );

  _revokeRole(role, account);
}

initialize keyboard_arrow_up

Parameters help

Name Type
_manager
address help
_migrator
address help

Properties

Visibility help public
Mutability help transaction

Modifiers help

Source Code
function initialize(address _manager, address _migrator) public initializer {
  _setupRole(MANAGER_ROLE, _manager);
  _setupRole(MIGRATOR_ROLE, _migrator);
  init_ = false;
}

init keyboard_arrow_up

Parameters help

Name Type
_mainTokenAddress
address help
_auctionAddress
address help
_subBalancesAddress
address help
_foreignSwapAddress
address help
_stakingV1Address
address help
_stepTimestamp
uint256 help

Properties

Visibility help public
Mutability help transaction

Modifiers help

onlyMigrator checks for the following:
null

Requirements help

Source Code
function init(
  address _mainTokenAddress,
  address _auctionAddress,
  address _subBalancesAddress,
  address _foreignSwapAddress,
  address _stakingV1Address,
  uint256 _stepTimestamp
) external onlyMigrator {
  require(!init_, "Staking: init is active");
  init_ = true;
  /** Setup */
  _setupRole(EXTERNAL_STAKER_ROLE, _foreignSwapAddress);
  _setupRole(EXTERNAL_STAKER_ROLE, _auctionAddress);

  addresses = Addresses({
    mainToken: _mainTokenAddress,
    auction: _auctionAddress,
    subBalances: _subBalancesAddress
  });

  stakingV1 = IStakingV1(_stakingV1Address);

  stepTimestamp = _stepTimestamp;

  if (startContract == 0) {
    startContract = now;
    nextPayoutCall = startContract.add(_stepTimestamp);
  }

  if (shareRate == 0) {
    shareRate = 1e18;
  }
}

sessionsOf_ keyboard_arrow_up

Parameters help

Name Type
account
address help

Properties

Visibility help public
Mutability help view
Source Code
function sessionsOf_(address account) external view returns (uint256[] memory) {
  return sessionsOf[account];
}

stake keyboard_arrow_up

Parameters help

Name Type
amount
uint256 help
stakingDays
uint256 help

Properties

Visibility help public
Mutability help transaction

Requirements help

Source Code
function stake(uint256 amount, uint256 stakingDays) external {
  if (now >= nextPayoutCall) makePayout();

  // Staking days must be greater then 0 and less then or equal to 5555.
  require(stakingDays != 0, "stakingDays < 1");
  require(stakingDays <= 5555, "stakingDays > 5555");

  uint256 start = now;
  uint256 end = now.add(stakingDays.mul(stepTimestamp));

  IToken(addresses.mainToken).burn(msg.sender, amount);
  lastSessionId = lastSessionId.add(1);
  uint256 sessionId = lastSessionId;
  uint256 shares = _getStakersSharesAmount(amount, start, end);
  sharesTotalSupply = sharesTotalSupply.add(shares);

  sessionDataOf[msg.sender][sessionId] = Session({
    amount: amount,
    start: start,
    end: end,
    shares: shares,
    firstPayout: payouts.length,
    lastPayout: payouts.length + stakingDays,
    withdrawn: false,
    payout: 0
  });

  sessionsOf[msg.sender].push(sessionId);

  ISubBalances(addresses.subBalances).callIncomeStakerTrigger(
    msg.sender,
    sessionId,
    start,
    end,
    shares
  );

  emit Stake(msg.sender, sessionId, amount, start, end, shares);
}

externalStake keyboard_arrow_up

Parameters help

Name Type
amount
uint256 help
stakingDays
uint256 help
staker
address help

Properties

Visibility help public
Mutability help transaction

Modifiers help

onlyExternalStaker checks for the following:
null

Requirements help

Source Code
function externalStake(
  uint256 amount,
  uint256 stakingDays,
  address staker
) external override onlyExternalStaker {
  if (now >= nextPayoutCall) makePayout();

  require(stakingDays != 0, "stakingDays < 1");
  require(stakingDays <= 5555, "stakingDays > 5555");

  uint256 start = now;
  uint256 end = now.add(stakingDays.mul(stepTimestamp));

  lastSessionId = lastSessionId.add(1);
  uint256 sessionId = lastSessionId;
  uint256 shares = _getStakersSharesAmount(amount, start, end);
  sharesTotalSupply = sharesTotalSupply.add(shares);

  sessionDataOf[staker][sessionId] = Session({
    amount: amount,
    start: start,
    end: end,
    shares: shares,
    firstPayout: payouts.length,
    lastPayout: payouts.length + stakingDays,
    withdrawn: false,
    payout: 0
  });

  sessionsOf[staker].push(sessionId);

  ISubBalances(addresses.subBalances).callIncomeStakerTrigger(
    staker,
    sessionId,
    start,
    end,
    shares
  );

  emit Stake(staker, sessionId, amount, start, end, shares);
}

calculateStakingInterest keyboard_arrow_up

Parameters help

Name Type
firstPayout
uint256 help
lastPayout
uint256 help
shares
uint256 help

Properties

Visibility help public
Mutability help view
Source Code
function calculateStakingInterest(
  uint256 firstPayout,
  uint256 lastPayout,
  uint256 shares
) public view returns (uint256) {
  uint256 stakingInterest;
  uint256 lastIndex = MathUpgradeable.min(payouts.length, lastPayout);

  for (uint256 i = firstPayout; i < lastIndex; i++) {
    uint256 payout = payouts[i].payout.mul(shares).div(
      payouts[i].sharesTotalSupply
    );

    stakingInterest = stakingInterest.add(payout);
  }

  return stakingInterest;
}

unstake keyboard_arrow_up

Parameters help

Name Type
sessionId
uint256 help

Properties

Visibility help public
Mutability help transaction

Requirements help

Source Code
function unstake(uint256 sessionId) external {
  if (now >= nextPayoutCall) makePayout();

  Session storage session = sessionDataOf[msg.sender][sessionId];

  require(
    session.shares != 0 && session.withdrawn == false,
    "Staking: Stake withdrawn/invalid"
  );

  uint256 actualEnd = now;
  uint256 amountOut = unstakeInternal(
    sessionId,
    session.amount,
    session.start,
    session.end,
    actualEnd,
    session.shares,
    session.firstPayout,
    session.lastPayout
  );

  ISubBalances(addresses.subBalances).callOutcomeStakerTrigger(
    sessionId,
    session.start,
    session.end,
    actualEnd,
    session.shares
  );

  session.end = actualEnd;
  session.withdrawn = true;
  session.payout = amountOut;
}

unstakeV1 keyboard_arrow_up

Parameters help

Name Type
sessionId
uint256 help

Properties

Visibility help public
Mutability help transaction
Source Code
function unstakeV1(uint256 sessionId) external {
  if (now >= nextPayoutCall) makePayout();

  require(sessionId <= lastSessionIdV1, "Staking: Invalid sessionId");

  Session storage session = sessionDataOf[msg.sender][sessionId];

  // Unstaked already
  require(
    session.shares == 0 && session.withdrawn == false,
    "Staking: Stake withdrawn"
  );

  (
    uint256 amount,
    uint256 start,
    uint256 end,
    uint256 shares,
    uint256 firstPayout
  ) = stakingV1.sessionDataOf(msg.sender, sessionId);

  // Unstaked in v1 / doesn't exist
  require(shares > 0, "Staking: Stake withdrawn");

  uint256 lastPayout = (end - start) / stepTimestamp + firstPayout;

  uint256 actualEnd = now;
  uint256 amountOut = unstakeInternal(
    sessionId,
    amount,
    start,
    end,
    actualEnd,
    shares,
    firstPayout,
    lastPayout
  );

  ISubBalances(addresses.subBalances).callOutcomeStakerTriggerV1(
    msg.sender,
    sessionId,
    start,
    end,
    actualEnd,
    shares
  );

  sessionDataOf[msg.sender][sessionId] = Session({
    amount: amount,
    start: start,
    end: actualEnd,
    shares: shares,
    firstPayout: firstPayout,
    lastPayout: lastPayout,
    withdrawn: true,
    payout: amountOut
  });

  sessionsOf[msg.sender].push(sessionId);
}

getAmountOutAndPenalty keyboard_arrow_up

Parameters help

Name Type
amount
uint256 help
start
uint256 help
end
uint256 help
stakingInterest
uint256 help

Properties

Visibility help public
Mutability help view
Source Code
function getAmountOutAndPenalty(
  uint256 amount,
  uint256 start,
  uint256 end,
  uint256 stakingInterest
) public view returns (uint256, uint256) {
  uint256 stakingSeconds = end.sub(start);
  uint256 stakingDays = stakingSeconds.div(stepTimestamp);
  uint256 secondsStaked = now.sub(start);
  uint256 daysStaked = secondsStaked.div(stepTimestamp);
  uint256 amountAndInterest = amount.add(stakingInterest);

  // Early
  if (stakingDays > daysStaked) {
    uint256 payOutAmount = amountAndInterest.mul(secondsStaked).div(
      stakingSeconds
    );

    uint256 earlyUnstakePenalty = amountAndInterest.sub(payOutAmount);

    return (payOutAmount, earlyUnstakePenalty);
    // In time
  } else if (daysStaked < stakingDays.add(14)) {
    return (amountAndInterest, 0);
    // Late
  } else if (daysStaked < stakingDays.add(714)) {
    uint256 daysAfterStaking = daysStaked - stakingDays;

    uint256 payOutAmount = amountAndInterest
    .mul(uint256(714).sub(daysAfterStaking))
    .div(700);

    uint256 lateUnstakePenalty = amountAndInterest.sub(payOutAmount);

    return (payOutAmount, lateUnstakePenalty);
    // Nothing
  } else {
    return (0, amountAndInterest);
  }
}

makePayout keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help public
Mutability help transaction
Source Code
function makePayout() public {
  require(now >= nextPayoutCall, "Staking: Wrong payout time");

  uint256 payout = _getPayout();

  payouts.push(Payout({payout: payout, sharesTotalSupply: sharesTotalSupply}));

  nextPayoutCall = nextPayoutCall.add(stepTimestamp);

  emit MakePayout(payout, sharesTotalSupply, now);
}

readPayout keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help public
Mutability help view
Source Code
function readPayout() external view returns (uint256) {
  uint256 amountTokenInDay = IERC20Upgradeable(addresses.mainToken).balanceOf(
    address(this)
  );

  uint256 currentTokenTotalSupply = (
    IERC20Upgradeable(addresses.mainToken).totalSupply()
  )
  .add(globalPayin);

  uint256 inflation = uint256(8)
  .mul(currentTokenTotalSupply.add(sharesTotalSupply))
  .div(36500);

  return amountTokenInDay.add(inflation);
}

setupRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help public
Mutability help transaction

Modifiers help

onlyManager checks for the following:
null
Source Code
function setupRole(bytes32 role, address account) external onlyManager {
  _setupRole(role, account);
}

Internal Functions Expand All Collapse All

Internal functions are parts of the contract that can't be used directly, but instead are used by the public functions listed above.

internal Staking._initPayout keyboard_arrow_up

Parameters help

Name Type
to
address help
amount
uint256 help

Properties

Visibility help internal
Mutability help transaction
Source Code
function _initPayout(address to, uint256 amount) internal {
  IToken(addresses.mainToken).mint(to, amount);
  globalPayout = globalPayout.add(amount);
}

internal Staking.unstakeInternal keyboard_arrow_up

Parameters help

Name Type
sessionId
uint256 help
amount
uint256 help
start
uint256 help
end
uint256 help
actualEnd
uint256 help
shares
uint256 help
firstPayout
uint256 help
lastPayout
uint256 help

Properties

Visibility help internal
Mutability help transaction
Source Code
function unstakeInternal(
  uint256 sessionId,
  uint256 amount,
  uint256 start,
  uint256 end,
  uint256 actualEnd,
  uint256 shares,
  uint256 firstPayout,
  uint256 lastPayout
) internal returns (uint256) {
  uint256 stakingInterest = calculateStakingInterest(
    firstPayout,
    lastPayout,
    shares
  );

  sharesTotalSupply = sharesTotalSupply.sub(shares);

  (uint256 amountOut, uint256 penalty) = getAmountOutAndPenalty(
    amount,
    start,
    end,
    stakingInterest
  );

  // To auction
  if (penalty != 0) {
    _initPayout(addresses.auction, penalty);
    IAuction(addresses.auction).callIncomeDailyTokensTrigger(penalty);
  }

  // To account
  _initPayout(msg.sender, amountOut);

  emit Unstake(msg.sender, sessionId, amountOut, start, actualEnd, shares);

  return amountOut;
}

internal Staking._getPayout keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help transaction
Source Code
function _getPayout() internal returns (uint256) {
  uint256 amountTokenInDay = IERC20Upgradeable(addresses.mainToken).balanceOf(
    address(this)
  );

  globalPayin = globalPayin.add(amountTokenInDay);

  if (globalPayin > globalPayout) {
    globalPayin = globalPayin.sub(globalPayout);
    globalPayout = 0;
  } else {
    globalPayin = 0;
    globalPayout = 0;
  }

  uint256 currentTokenTotalSupply = (
    IERC20Upgradeable(addresses.mainToken).totalSupply()
  )
  .add(globalPayin);

  IToken(addresses.mainToken).burn(address(this), amountTokenInDay);

  uint256 inflation = uint256(8)
  .mul(currentTokenTotalSupply.add(sharesTotalSupply))
  .div(36500);

  globalPayin = globalPayin.add(inflation);

  return amountTokenInDay.add(inflation);
}

internal Staking._getStakersSharesAmount keyboard_arrow_up

Parameters help

Name Type
amount
uint256 help
start
uint256 help
end
uint256 help

Properties

Visibility help internal
Mutability help view
Source Code
function _getStakersSharesAmount(
  uint256 amount,
  uint256 start,
  uint256 end
) internal view returns (uint256) {
  uint256 stakingDays = (end.sub(start)).div(stepTimestamp);
  uint256 numerator = amount.mul(uint256(1819).add(stakingDays));
  uint256 denominator = uint256(1820).mul(shareRate);

  return (numerator).mul(1e18).div(denominator);
}

internal Staking._getShareRate keyboard_arrow_up

Parameters help

Name Type
amount
uint256 help
shares
uint256 help
start
uint256 help
end
uint256 help
stakingInterest
uint256 help

Properties

Visibility help internal
Mutability help view
Source Code
function _getShareRate(
  uint256 amount,
  uint256 shares,
  uint256 start,
  uint256 end,
  uint256 stakingInterest
) internal view returns (uint256) {
  uint256 stakingDays = (end.sub(start)).div(stepTimestamp);

  uint256 numerator = (amount.add(stakingInterest)).mul(
    uint256(1819).add(stakingDays)
  );

  uint256 denominator = uint256(1820).mul(shares);

  return (numerator).mul(1e18).div(denominator);
}

internal Initializable._isConstructor keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help private
Mutability help view
Source Code
function _isConstructor() private view returns (bool) {
  // extcodesize checks the size of the code stored in an address, and
  // address returns the current address. Since the code is still not
  // deployed when running a constructor, any checks on its code size will
  // yield zero, making it an effective way to detect if a contract is
  // under construction or not.
  address self = address(this);
  uint256 cs;
  // solhint-disable-next-line no-inline-assembly
  assembly {
    cs := extcodesize(self)
  }
  return cs == 0;
}

internal AccessControlUpgradeable.__AccessControl_init keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help transaction

Modifiers help

Source Code
function __AccessControl_init() internal initializer {
  __Context_init_unchained();
  __AccessControl_init_unchained();
}

internal AccessControlUpgradeable.__AccessControl_init_unchained keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help transaction

Modifiers help

Source Code
function __AccessControl_init_unchained() internal initializer {}

internal AccessControlUpgradeable._setupRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help internal
Mutability help transaction
Source Code
function _setupRole(bytes32 role, address account) internal virtual {
  _grantRole(role, account);
}

internal AccessControlUpgradeable._setRoleAdmin keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
adminRole
bytes32 help

Properties

Visibility help internal
Mutability help transaction
Source Code
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
  emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
  _roles[role].adminRole = adminRole;
}

internal AccessControlUpgradeable._grantRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help private
Mutability help transaction
Source Code
function _grantRole(bytes32 role, address account) private {
  if (_roles[role].members.add(account)) {
    emit RoleGranted(role, account, _msgSender());
  }
}

internal AccessControlUpgradeable._revokeRole keyboard_arrow_up

Parameters help

Name Type
role
bytes32 help
account
address help

Properties

Visibility help private
Mutability help transaction
Source Code
function _revokeRole(bytes32 role, address account) private {
  if (_roles[role].members.remove(account)) {
    emit RoleRevoked(role, account, _msgSender());
  }
}

internal Initializable._isConstructor keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help private
Mutability help view
Source Code
function _isConstructor() private view returns (bool) {
  // extcodesize checks the size of the code stored in an address, and
  // address returns the current address. Since the code is still not
  // deployed when running a constructor, any checks on its code size will
  // yield zero, making it an effective way to detect if a contract is
  // under construction or not.
  address self = address(this);
  uint256 cs;
  // solhint-disable-next-line no-inline-assembly
  assembly {
    cs := extcodesize(self)
  }
  return cs == 0;
}

internal ContextUpgradeable.__Context_init keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help transaction

Modifiers help

Source Code
function __Context_init() internal initializer {
  __Context_init_unchained();
}

internal ContextUpgradeable.__Context_init_unchained keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help transaction

Modifiers help

Source Code
function __Context_init_unchained() internal initializer {}

internal ContextUpgradeable._msgSender keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help view
Source Code
function _msgSender() internal view virtual returns (address payable) {
  return msg.sender;
}

internal ContextUpgradeable._msgData keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help view
Source Code
function _msgData() internal view virtual returns (bytes memory) {
  this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
  return msg.data;
}

internal Initializable._isConstructor keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help private
Mutability help view
Source Code
function _isConstructor() private view returns (bool) {
  // extcodesize checks the size of the code stored in an address, and
  // address returns the current address. Since the code is still not
  // deployed when running a constructor, any checks on its code size will
  // yield zero, making it an effective way to detect if a contract is
  // under construction or not.
  address self = address(this);
  uint256 cs;
  // solhint-disable-next-line no-inline-assembly
  assembly {
    cs := extcodesize(self)
  }
  return cs == 0;
}