Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
6 changes: 6 additions & 0 deletions contracts/Minter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ 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) {
toMint = toMint + registry.getPendingBalance(recipient);
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
98 changes: 96 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 private 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"
);
_;
}

//
// EXTERNAL FUNCTIONS:
Expand Down Expand Up @@ -117,6 +154,62 @@ 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)
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
{
require(
_adr != address(0),
"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);
}

function clearPendingBalance(address _adr)
external
onlyMinter
{
require(
_adr != address(0),
"Cannot consume pending balance for zero balance"
);

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

emit PendingBalanceCleared(_adr, pendingBalance);
}

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

EnumerableSet.remove(accounts, _adr);
delete maxTrusts[_adr];
delete pendingBalances[_adr];

emit ContributorRemoved(_adr);
}
Expand Down
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