recommendations

This commit is contained in:
Jarrad Hope 2019-02-10 13:43:35 +07:00
parent 55d2bc14d0
commit c45cd363b9
No known key found for this signature in database
GPG Key ID: D549F0EF6ACE1FE7
2 changed files with 105 additions and 60 deletions

View File

@ -702,5 +702,53 @@
"address": "0x9c888ff4D7d4F512C79073ad5016116327fD8315" "address": "0x9c888ff4D7d4F512C79073ad5016116327fD8315"
} }
} }
},
"0x49d86540d21be243d6b35ac3d57a70a706f7deb3bb86ef077f4284cd96c49996": {
"contracts": {
"0xe5413cb03538126884d14df481da47efdeba969bd6c7e3609abaf1dc42973b1a": {
"name": "MiniMeTokenFactory",
"address": "0x7078E9E73FeFf15eC5C4C58233adc19447719979"
},
"0x1dc86cbe444c7243c6565fc68d02a9a0623e97a7d9470f1debede7951c2acb37": {
"name": "SNT",
"address": "0x195fcB5B1D04E58C90813a5d67a5Ab84Bc4D85e5"
},
"0xdbb86398e138a56d6f9aedadef62d41d99e5a3c6a39d64605ec1e4ad2ed03552": {
"name": "Meritocracy",
"address": "0x9c888ff4D7d4F512C79073ad5016116327fD8315"
}
}
},
"0xafffa90a8bde013ecfaa2f52c9e3a91cec80efb2bf21a11aa6322dd14cdcff9f": {
"contracts": {
"0xe5413cb03538126884d14df481da47efdeba969bd6c7e3609abaf1dc42973b1a": {
"name": "MiniMeTokenFactory",
"address": "0x7078E9E73FeFf15eC5C4C58233adc19447719979"
},
"0x1dc86cbe444c7243c6565fc68d02a9a0623e97a7d9470f1debede7951c2acb37": {
"name": "SNT",
"address": "0x195fcB5B1D04E58C90813a5d67a5Ab84Bc4D85e5"
},
"0xdbb86398e138a56d6f9aedadef62d41d99e5a3c6a39d64605ec1e4ad2ed03552": {
"name": "Meritocracy",
"address": "0x9c888ff4D7d4F512C79073ad5016116327fD8315"
}
}
},
"0xb78c5af6ccf56c3a3467561d3ae57a6446fd2239d3b1ad07cc6c9a0bd0a865d2": {
"contracts": {
"0xe5413cb03538126884d14df481da47efdeba969bd6c7e3609abaf1dc42973b1a": {
"name": "MiniMeTokenFactory",
"address": "0x7078E9E73FeFf15eC5C4C58233adc19447719979"
},
"0x1dc86cbe444c7243c6565fc68d02a9a0623e97a7d9470f1debede7951c2acb37": {
"name": "SNT",
"address": "0x195fcB5B1D04E58C90813a5d67a5Ab84Bc4D85e5"
},
"0x78671fa87a2081dd20332ebf134a0e2dab79f47bfe878fb8911921d78dbad054": {
"name": "Meritocracy",
"address": "0x9c888ff4D7d4F512C79073ad5016116327fD8315"
}
}
} }
} }

View File

@ -12,6 +12,11 @@ DApp:
- allows you to send SNT to meritocracy - allows you to send SNT to meritocracy
- add/remove contributor - add/remove contributor
- add/remove adminstrator - add/remove adminstrator
Extension:
- Command:
- above command = display allocation, received, withdraw button, allocate button? (might be better in dapp)
- /kudos 500 "<person>" "<praise>"
*/ */
import "token/ERC20Token.sol"; import "token/ERC20Token.sol";
@ -35,7 +40,7 @@ contract Meritocracy {
Status[] status; Status[] status;
} }
address public token; // token contract ERC20Token public token; // token contract
address payable public owner; // contract owner address payable public owner; // contract owner
uint256 public lastForfeit; // timestamp to block admins calling forfeitAllocations too quickly uint256 public lastForfeit; // timestamp to block admins calling forfeitAllocations too quickly
address[] public registry; // array of contributor addresses address[] public registry; // array of contributor addresses
@ -43,16 +48,30 @@ contract Meritocracy {
mapping(address => bool) public admins; mapping(address => bool) public admins;
mapping(address => Contributor) public contributors; mapping(address => Contributor) public contributors;
// Modifiers -------------------------------------------------------------------------------------------------
// Functions only Owner can call
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
// Functions only Admin can call
modifier onlyAdmin() {
require(admins[msg.sender]);
_;
}
// Open Functions ---------------------------------------------------------------------------------------- // Open Functions ----------------------------------------------------------------------------------------
// Split amount over each contributor in registry, anyone can contribute. // Split amount over each contributor in registry, any contributor can allocate? TODO maybe relax this restriction, so anyone can allocate tokens
function allocate(uint256 _amount) external { function allocate(uint256 _amount) external {
// Locals // Locals
uint256 individualAmount; uint256 individualAmount;
Contributor memory cAllocator = contributors[msg.sender]; // Contributor memory cAllocator = contributors[msg.sender];
// Requirements // Requirements
require(cAllocator.addr == msg.sender); // is sender a Contributor? // require(cAllocator.addr != address(0)); // is sender a Contributor? TODO maybe relax this restriction.
require(ERC20Token(token).transferFrom(msg.sender, address(this), _amount)); require(token.transferFrom(msg.sender, address(this), _amount));
// Body // Body
// cAllocator.inPot = true; // cAllocator.inPot = true;
individualAmount = _amount / registry.length; individualAmount = _amount / registry.length;
@ -62,7 +81,7 @@ contract Meritocracy {
} }
// Getter for Dynamic Array Length // Getter for Dynamic Array Length
function registryLength() external returns (uint256) { function registryLength() public view returns (uint256) {
return registry.length; return registry.length;
} }
@ -81,7 +100,7 @@ contract Meritocracy {
uint256 r = cReceiver.received; uint256 r = cReceiver.received;
cReceiver.received = 0; cReceiver.received = 0;
// cReceiver.inPot = false; // cReceiver.inPot = false;
ERC20Token(token).transferFrom(address(this), cReceiver.addr, r); token.transferFrom(address(this), cReceiver.addr, r);
} }
// Allow Contributors to award allocated tokens to other Contributors // Allow Contributors to award allocated tokens to other Contributors
@ -112,11 +131,10 @@ contract Meritocracy {
// Admin Functions ------------------------------------------------------------------------------------- // Admin Functions -------------------------------------------------------------------------------------
// Add Contributor to Registry // Add Contributor to Registry
function addContributor(address _contributor) public { function addContributor(address _contributor) public onlyAdmin() {
// Requirements // Requirements
require(admins[msg.sender]); require(registry.length + 1 <= maxContributors); // Don't go out of bounds
require(registry.length + 1 <= maxContributors); require(contributors[_contributor].addr == address(0)); // Contributor doesn't exist
require(contributors[_contributor].addr == address(0));
// Body // Body
Contributor storage c = contributors[_contributor]; Contributor storage c = contributors[_contributor];
c.addr = _contributor; c.addr = _contributor;
@ -124,9 +142,9 @@ contract Meritocracy {
} }
// Add Multiple Contributors to the Registry in one tx // Add Multiple Contributors to the Registry in one tx
function addContributors(address[] calldata _newContributors ) external { function addContributors(address[] calldata _newContributors ) external onlyAdmin() {
// Requirements // Requirements
require(registry.length + _newContributors.length <= maxContributors); require(registry.length + _newContributors.length <= maxContributors); // Don't go out of bounds
// Body // Body
for (uint256 i = 0; i < _newContributors.length; i++) { for (uint256 i = 0; i < _newContributors.length; i++) {
addContributor(_newContributors[i]); addContributor(_newContributors[i]);
@ -135,19 +153,19 @@ contract Meritocracy {
// Remove Contributor from Registry // Remove Contributor from Registry
// Note: Should not be easy to remove multiple contributors in one tx // Note: Should not be easy to remove multiple contributors in one tx
function removeContributor(address _contributor) external { // WARN: Changed to idx, client can do loop by enumerating registry
function removeContributor(uint256 idx) external onlyAdmin() { // address _contributor
// Requirements // Requirements
require(admins[msg.sender]); require(idx < registry.length - 1); // idx needs to be smaller than registry.length - 1 OR maxContributors
// Body // Body
// Find id of contributor address // Find id of contributor address
uint256 idx = 0; // uint256 idx = 0;
for (uint256 i = 0; i < registry.length; i++) { // should never be longer than maxContributors, see addContributor // for (uint256 i = 0; i < registry.length; i++) { // should never be longer than maxContributors, see addContributor
if (registry[i] == _contributor) { // if (registry[i] == _contributor) {
idx = i; // idx = i;
break; // break;
} // }
} // }
address c = registry[idx]; address c = registry[idx];
// Swap & Pop! // Swap & Pop!
registry[idx] = registry[registry.length - 1]; registry[idx] = registry[registry.length - 1];
@ -156,18 +174,14 @@ contract Meritocracy {
} }
// Implictly sets a finite limit to registry length // Implictly sets a finite limit to registry length
function setMaxContributors(uint256 _maxContributors) external { function setMaxContributors(uint256 _maxContributors) external onlyAdmin() {
// Requirements
require(admins[msg.sender]);
require(_maxContributors > registry.length); // have to removeContributor first require(_maxContributors > registry.length); // have to removeContributor first
// Body // Body
maxContributors = _maxContributors; maxContributors = _maxContributors;
} }
// Zero-out allocations for contributors, minimum once a week, if allocation still exists, add to burn // Zero-out allocations for contributors, minimum once a week, if allocation still exists, add to burn
function forfeitAllocations() public { function forfeitAllocations() public onlyAdmin() {
// Requirements
require(admins[msg.sender]);
require(block.timestamp >= lastForfeit + 1 weeks); // prevents multiple admins accidently calling too quickly. require(block.timestamp >= lastForfeit + 1 weeks); // prevents multiple admins accidently calling too quickly.
// Body // Body
lastForfeit = block.timestamp; lastForfeit = block.timestamp;
@ -183,25 +197,17 @@ contract Meritocracy {
// Owner Functions ------------------------------------------------------------------------------------- // Owner Functions -------------------------------------------------------------------------------------
// Set Admin flag for address to true // Set Admin flag for address to true
function addAdmin(address _admin) public { function addAdmin(address _admin) public onlyOwner() {
// Requirements
require(msg.sender == owner);
// Body
admins[_admin] = true; admins[_admin] = true;
} }
// Set Admin flag for address to false // Set Admin flag for address to false
function removeAdmin(address _admin) public { function removeAdmin(address _admin) public onlyOwner() {
// Requirements
require(msg.sender == owner);
// Body
delete admins[_admin]; delete admins[_admin];
} }
// Change owner address, ideally to a management contract or multisig // Change owner address, ideally to a management contract or multisig
function changeOwner(address payable _owner) external { function changeOwner(address payable _owner) external onlyOwner() {
// Requirements
require(msg.sender == owner);
// Body // Body
removeAdmin(owner); removeAdmin(owner);
addAdmin(_owner); addAdmin(_owner);
@ -210,41 +216,34 @@ contract Meritocracy {
// Change Token address // Change Token address
// WARN: call escape first, or escape(token); // WARN: call escape first, or escape(token);
function changeToken(address _token) external { function changeToken(address _token) external onlyOwner() {
// Locals
uint256 r;
// Requirements
require(msg.sender == owner);
// Body // Body
// Zero-out allocation and received, send out received tokens before token switch. // Zero-out allocation and received, send out received tokens before token switch.
for (uint256 i = 0; i < registry.length; i++) { for (uint256 i = 0; i < registry.length; i++) {
Contributor storage c = contributors[registry[i]]; Contributor storage c = contributors[registry[i]];
r = c.received; uint256 r = c.received;
c.received = 0; c.received = 0;
c.allocation = 0; c.allocation = 0;
// WARN: Should totalReceived and totalForfeited be zeroed-out? // WARN: Should totalReceived and totalForfeited be zeroed-out?
ERC20Token(token).transferFrom(address(this), c.addr, r); // Transfer any owed tokens to contributor token.transferFrom(address(this), c.addr, r); // Transfer any owed tokens to contributor
} }
lastForfeit = block.timestamp; lastForfeit = block.timestamp;
token = _token; token = ERC20Token(_token);
} }
// Failsafe, Owner can escape hatch all Tokens and ETH from Contract. // Failsafe, Owner can escape hatch all Tokens and ETH from Contract.
function escape() public { function escape() public onlyOwner() {
// Requirements
require(msg.sender == owner);
// Body // Body
ERC20Token(token).transferFrom(address(this), owner, ERC20Token(token).balanceOf(address(this))); token.transferFrom(address(this), owner, token.balanceOf(address(this)));
address(owner).transfer(address(this).balance); owner.transfer(address(this).balance);
} }
// Overloaded failsafe function, recourse incase changeToken is called before escape and funds are in a different token // Overloaded failsafe function, recourse incase changeToken is called before escape and funds are in a different token
// Don't want to require in changeToken incase bad behaviour of ERC20 token // Don't want to require in changeToken incase bad behaviour of ERC20 token
function escape(address _token) external { function escape(address _token) external onlyOwner() {
// Requirements
require(msg.sender == owner);
// Body // Body
ERC20Token(_token).transferFrom(address(this), owner, ERC20Token(_token).balanceOf(address(this))); ERC20Token t = ERC20Token(_token);
t.transferFrom(address(this), owner, t.balanceOf(address(this)));
escape(); escape();
} }
@ -254,9 +253,7 @@ contract Meritocracy {
owner = msg.sender; owner = msg.sender;
addAdmin(owner); addAdmin(owner);
lastForfeit = block.timestamp; lastForfeit = block.timestamp;
token = _token; token = ERC20Token(_token);
maxContributors= _maxContributors; maxContributors= _maxContributors;
} }
// function() public { throw; } // TODO Probably not needed?
} }