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 8 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
119 changes: 117 additions & 2 deletions contracts/registry/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ 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";

/// @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;

//
Expand All @@ -17,9 +19,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) pendingBalances;

//
// EVENTS:
//
Expand All @@ -30,13 +41,39 @@ 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 changed:
event PendingBalanceChanged(address indexed adr, uint256 pendingBalance);

/// @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 Down Expand Up @@ -117,6 +154,67 @@ 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 = pendingBalances[_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 balance
/// @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]);
}
}

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 = pendingBalances[_adr];
delete pendingBalances[_adr];

emit PendingBalanceCleared(_adr, pendingBalance);
}

//
// INTERNAL FUNCTIONS:
//
Expand All @@ -140,7 +238,24 @@ contract Registry is AdminRole {

EnumerableSet.remove(accounts, _adr);
aminlatifi marked this conversation as resolved.
Show resolved Hide resolved
delete maxTrusts[_adr];
delete pendingBalances[_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"
);

pendingBalances[_adr] = _pendingBalance;

emit PendingBalanceChanged(_adr, _pendingBalance);
}
}
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