Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F pending balance #42

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions contracts/Minter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ contract Minter is AdminRole {
// Get the current CSTK balance of the recipient account.
uint256 recipientBalance = cstkToken.balanceOf(recipient);

// It's activating membership too
if (recipientBalance == 0) {
uint256 pendingBalance = registry.getPendingBalance(recipient);
toMint = toMint + pendingBalance;
if (pendingBalance != 0) {
registry.clearPendingBalance(recipient);
}
}

// The recipient cannot receive more than the following amount of tokens:
// maxR := maxTrust[recipient] * TOTAL_SUPPLY / 10000000.
uint256 maxToReceive = maxTrust.mul(totalSupply).div(
Expand Down
208 changes: 196 additions & 12 deletions contracts/registry/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ pragma solidity ^0.5.17;
import "./AdminRole.sol";

import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/GSN/Context.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";

/// @title Registry tracks trusted contributors: accounts and their max trust.
// Max trust will determine the maximum amount of tokens the account can obtain.
/// @author Nelson Melina
contract Registry is AdminRole {
contract Registry is Context, AdminRole {
using EnumerableSet for EnumerableSet.AddressSet;
using SafeMath for uint256;

//
// STORAGE:
Expand All @@ -17,9 +21,18 @@ contract Registry is AdminRole {
// EnumerableSet of all trusted accounts:
EnumerableSet.AddressSet internal accounts;

// CS token contract
IERC20 internal cstkToken;

// Minter contract address
address public minterContract;

// Mapping of account => contributor max trust:
mapping(address => uint256) maxTrusts;

// Mapping of account => contributor pending balance:
mapping(address => uint256) balances;

//
// EVENTS:
//
Expand All @@ -30,13 +43,42 @@ contract Registry is AdminRole {
/// @dev Emit when a contributor has been removed:
event ContributorRemoved(address adr);

/// @dev Emit when a contributor's pending balance is set:
event PendingBalanceSet(address indexed adr, uint256 pendingBalance);

/// @dev Emit when a contributor's pending balance is risen:
event PendingBalanceRise(address indexed adr, uint256 value);

/// @dev Emit when a contributor's pending balance is cleared:
event PendingBalanceCleared(
address indexed adr,
uint256 consumedPendingBalance
);

/// @dev Emit when minter contract address is set
event MinterContractSet(address indexed adr);

//
// CONSTRUCTOR:
//

/// @dev Construct the Registry,
/// @param _admins (address[]) List of admins for the Registry contract.
constructor(address[] memory _admins) public AdminRole(_admins) {}
/// @param _cstkTokenAddress (address) CS token deployed contract address
constructor(address[] memory _admins, address _cstkTokenAddress)
public
AdminRole(_admins)
{
cstkToken = IERC20(_cstkTokenAddress);
}

modifier onlyMinter() {
require(
_msgSender() == minterContract,
"Caller is not Minter Contract"
);
_;
}
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved

//
// EXTERNAL FUNCTIONS:
Expand All @@ -46,11 +88,13 @@ contract Registry is AdminRole {
/// @dev Can only be called by Admin role.
/// @param _adr (address) The address to register as contributor
/// @param _maxTrust (uint256) The amount to set as max trust
function registerContributor(address _adr, uint256 _maxTrust)
external
onlyAdmin
{
_register(_adr, _maxTrust);
/// @param _pendingBalance (uint256) The amount to set as pending balance
function registerContributor(
address _adr,
uint256 _maxTrust,
uint256 _pendingBalance
) external onlyAdmin {
_register(_adr, _maxTrust, _pendingBalance);
}

/// @notice Remove an existing contributor.
Expand All @@ -65,16 +109,18 @@ contract Registry is AdminRole {
/// @param _cnt (uint256) Number of contributors to add
/// @param _adrs (address[]) Addresses to register as contributors
/// @param _trusts (uint256[]) Max trust values to set to each contributor (in order)
/// @param _pendingBalances (uint256[]) pending balance values to set to each contributor (in order)
function registerContributors(
uint256 _cnt,
address[] calldata _adrs,
uint256[] calldata _trusts
uint256[] calldata _trusts,
uint256[] calldata _pendingBalances
) external onlyAdmin {
require(_adrs.length == _cnt, "Invalid number of addresses");
require(_trusts.length == _cnt, "Invalid number of trust values");

for (uint256 i = 0; i < _cnt; i++) {
_register(_adrs[i], _trusts[i]);
_register(_adrs[i], _trusts[i], _pendingBalances[i]);
}
}

Expand All @@ -91,19 +137,26 @@ contract Registry is AdminRole {
/// @notice Return contributor information about all accounts in the Registry.
/// @return contrubutors (address[]) Adresses of all contributors
/// @return trusts (uint256[]) Max trust values for all contributors, in order.
/// @return pendingBalances (uint256[]) Pending balance values for all contributors, in order.
function getContributorInfo()
external
view
returns (address[] memory contributors, uint256[] memory trusts)
returns (
address[] memory contributors,
uint256[] memory trusts,
uint256[] memory pendingBalances
)
{
contributors = EnumerableSet.enumerate(accounts);
uint256 len = contributors.length;

trusts = new uint256[](len);
pendingBalances = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
trusts[i] = maxTrusts[contributors[i]];
pendingBalances[i] = balances[contributors[i]];
}
return (contributors, trusts);
return (contributors, trusts, pendingBalances);
}

/// @notice Return the max trust of an address, or 0 if the address is not a contributor.
Expand All @@ -117,11 +170,105 @@ contract Registry is AdminRole {
return maxTrusts[_adr];
}

/// @notice Return the pending balance of an address, or 0 if the address is not a contributor.
/// @param _adr (address) Address to check
/// @return pendingBalance (uint256) Pending balance of the address, or 0 if not a contributor.
function getPendingBalance(address _adr)
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved
external
view
returns (uint256 pendingBalance)
{
pendingBalance = balances[_adr];
}

// @notice Set minter contract address
// @param _minterContract (address) Address to set
function setMinterContract(address _minterContract) external onlyAdmin {
minterContract = _minterContract;

emit MinterContractSet(_minterContract);
}

// @notice Set pending balance of an address
// @param _adr (address) Address to set
// @param _pendingBalance (uint256) Pending balance of the address
function setPendingBalance(address _adr, uint256 _pendingBalance)
external
onlyAdmin
{
_setPendingBalance(_adr, _pendingBalance);
}

/// @notice Set a list of contributors pending balances
/// @dev Can only be called by Admin role.
/// @param _cnt (uint256) Number of contributors to set pending balance
/// @param _adrs (address[]) Addresses to set pending balance
/// @param _pendingBalances (uint256[]) Pending balance values to set to each contributor (in order)
function setPendingBalances(
uint256 _cnt,
address[] calldata _adrs,
uint256[] calldata _pendingBalances
) external onlyAdmin {
require(_adrs.length == _cnt, "Invalid number of addresses");
require(
_pendingBalances.length == _cnt,
"Invalid number of trust values"
);

for (uint256 i = 0; i < _cnt; i++) {
_setPendingBalance(_adrs[i], _pendingBalances[i]);
}
}

// @notice Add pending balance of an address
// @param _adr (address) Address to set
// @param _value (uint256) Value to add to pending balance of the address
function addPendingBalance(address _adr, uint256 _value)
external
onlyAdmin
{
_addPendingBalance(_adr, _value);
}

/// @notice Add to a list of contributors' pending balances
/// @dev Can only be called by Admin role.
/// @param _cnt (uint256) Number of contributors to add pending balance
/// @param _adrs (address[]) Addresses to add pending balance
/// @param _values (uint256[]) Values to add to pending balance of each contributor (in order)
function addPendingBalances(
uint256 _cnt,
address[] calldata _adrs,
uint256[] calldata _values
) external onlyAdmin {
require(_adrs.length == _cnt, "Invalid number of addresses");
require(_values.length == _cnt, "Invalid number of trust values");

for (uint256 i = 0; i < _cnt; i++) {
_addPendingBalance(_adrs[i], _values[i]);
}
}

function clearPendingBalance(address _adr) external onlyMinter {
require(
_adr != address(0),
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved
"Cannot consume pending balance for zero balance"
);

uint256 pendingBalance = balances[_adr];
delete balances[_adr];

emit PendingBalanceCleared(_adr, pendingBalance);
}

//
// INTERNAL FUNCTIONS:
//

function _register(address _adr, uint256 _trust) internal {
function _register(
address _adr,
uint256 _trust,
uint256 _pendingBalance
) internal {
require(_adr != address(0), "Cannot register zero address");
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved
require(_trust != 0, "Cannot set a max trust of 0");

Expand All @@ -130,6 +277,7 @@ contract Registry is AdminRole {
"Contributor already registered"
);
maxTrusts[_adr] = _trust;
balances[_adr] = _pendingBalance;

emit ContributorAdded(_adr);
}
Expand All @@ -140,7 +288,43 @@ contract Registry is AdminRole {

EnumerableSet.remove(accounts, _adr);
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved
delete maxTrusts[_adr];
delete balances[_adr];

emit ContributorRemoved(_adr);
}

function _setPendingBalance(address _adr, uint256 _pendingBalance)
internal
{
require(
_adr != address(0),
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved
"Cannot set pending balance for zero balance"
);
require(maxTrusts[_adr] != 0, "Address is not a contributor");
require(
cstkToken.balanceOf(_adr) == 0,
"User has activated his membership"
);

balances[_adr] = _pendingBalance;

emit PendingBalanceSet(_adr, _pendingBalance);
}

function _addPendingBalance(address _adr, uint256 _value) internal {
require(
_adr != address(0),
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved
"Cannot set pending balance for zero balance"
);
require(maxTrusts[_adr] != 0, "Address is not a contributor");
require(
cstkToken.balanceOf(_adr) == 0,
"User has activated his membership"
);

uint256 newPendingBalance = balances[_adr].add(_value);
balances[_adr] = newPendingBalance;

emit PendingBalanceRise(_adr, _value);
}
}
37 changes: 21 additions & 16 deletions buidler.config.ts → hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { BuidlerConfig, task, usePlugin } from "@nomiclabs/buidler/config";
import { HardhatUserConfig, task } from "hardhat/config";
import { generate, get } from "./scripts/accounts";

import { remove } from "fs-extra";
import "@nomiclabs/hardhat-ethers";
import "@nomiclabs/hardhat-etherscan";

require("dotenv-safe").config();
import "hardhat-deploy";
import "hardhat-gas-reporter";
import "solidity-coverage";

usePlugin("@nomiclabs/buidler-ethers");
usePlugin("@nomiclabs/buidler-etherscan");
usePlugin("buidler-deploy");
usePlugin("buidler-gas-reporter");
usePlugin("solidity-coverage");
require("dotenv-safe").config({
allowEmptyValues: true,
});

require("./scripts/trustedAccounts");
require("./scripts/addTrusted");
Expand All @@ -26,7 +28,7 @@ const SOLC_VERSION = process.env.SOLC_VERSION || "";
const SOLC_OPTIMIZER_ENABLED = process.env.SOLC_OPTIMIZER_ENABLED === "true";
const GAS_REPORTER_ENABLED = process.env.GAS_REPORTER_ENABLED === "true";

const config: BuidlerConfig = {
const config: HardhatUserConfig = {
paths: {
artifacts: "build/contracts",
cache: "build/cache",
Expand All @@ -35,7 +37,7 @@ const config: BuidlerConfig = {
tests: "test",
},
networks: {
buidlerevm: {
hardhat: {
accounts: generate(MNEMONIC, DEVCHAIN_ACCOUNT_NUM, DEVCHAIN_BALANCE_ETH),
},
local: {
Expand All @@ -61,21 +63,24 @@ const config: BuidlerConfig = {
drainVaultReceiver: { default: 0 },
escapeHatchCaller: { default: 0 },
escapeHatchDestination: { default: 0 },
other: { default: 9 },
other: { default: 8 },
otherSecond: { default: 9 },
},
solc: {
solidity: {
version: SOLC_VERSION,
optimizer: {
runs: 200,
enabled: SOLC_OPTIMIZER_ENABLED,
settings: {
optimizer: {
runs: 200,
enabled: SOLC_OPTIMIZER_ENABLED,
},
},
},
gasReporter: {
enabled: GAS_REPORTER_ENABLED,
artifactType: "buidler-v1",
// artifactType: "buidler-v1",
},
etherscan: {
url: "https://api.etherscan.io/api",
// url: "https://api.etherscan.io/api",
apiKey: ETHERSCAN_API_KEY,
},
};
Expand Down
Loading