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

Refactor/adding require failure messages #265

Merged
merged 13 commits into from Sep 11, 2019
@@ -29,8 +29,7 @@ local KosuGeth(name) = Image(name, "kosu-test-geth:latest") {
"name": "tests",
"steps": [
Image("prettier_project", "node-lts:latest") {
"commands": ["yarn prettier:ci"],
"depends_on": ["clone"],
"commands": ["yarn prettier:ci"]
},

Image("build-project", "node-lts:latest") + GethConfig() {
@@ -40,8 +39,7 @@ local KosuGeth(name) = Image(name, "kosu-test-geth:latest") {
"cd packages/kosu-system-contracts",
"yarn migrate:ci",
"WEB3_URI=http://go-kosu-ci-geth:8545 yarn migrate:ci"
],
"depends_on": ["clone"]
]
},

Image("npm-tests", "node-lts:latest") + GethConfig() {
@@ -12,8 +12,6 @@ steps:
image: gcr.io/kosu-io/node-lts:latest
commands:
- yarn prettier:ci
depends_on:
- clone

- name: build-project
pull: always
@@ -27,8 +25,6 @@ steps:
environment:
WEB3_URI: http://kosu-geth:8545
WEB3_URI_WS: ws://kosu-geth:8546
depends_on:
- clone

- name: npm-tests
pull: always
@@ -0,0 +1,9 @@
version: '3'
services:
kosu:
build:
context: .
dockerfile: kosu-test.Dockerfile
ports:
- 8545:8545
- 8546:8546
@@ -8,6 +8,7 @@
"geth:init": "yarn geth:clean && geth init genesis.json --datadir .",
"geth:start:old": "geth --datadir . --networkid 6174 --rpc --rpcaddr '0.0.0.0' --unlock=\"`cat accounts`\" --password=./passwords --etherbase \"0x54E60Bccc86A7Bad4BC68E36a8fde0F369aE849E\" --mine --rpccorsdomain '*' --rpcapi 'personal,db,eth,net,web3,txpool,miner,debug' console",
"kosu:start": "docker-compose up --force-recreate --build",
"kosu:test:start": "docker-compose -f docker-compose.test.yml up --force-recreate --build",
"build:kosu": "scripts/build-and-push-geth-image.sh kosu.Dockerfile ${npm_package_config_image_host} kosu-geth ${npm_package_version}",
"build:kosu-test": "scripts/build-and-push-geth-image.sh kosu-test.Dockerfile ${npm_package_config_image_host} kosu-test-geth ${npm_package_version}",
"build_and_push": "yarn build:kosu && yarn build:kosu-test"
@@ -23,7 +23,7 @@ contract AuthorizedAddresses is Ownable {
@param a Address to authorize
*/
function authorizeAddress(address a) public {
require(authorizedAddresses[msg.sender]);
require(authorizedAddresses[msg.sender], "unauthorized");
authorizedAddresses[a] = true;
}

@@ -23,7 +23,7 @@ contract Authorizable {
@notice Ensures msg.sender is authorized within the AuthorizedAddresses contract
*/
modifier isAuthorized() {
require(authorizedAddress.isAddressAuthorized(msg.sender));
require(authorizedAddress.isAddressAuthorized(msg.sender), "unauthorized");
_;
}
}
@@ -38,7 +38,7 @@ contract KosuToken is ERC20, Authorizable {

uint tokensToMint = calculateEtherToToken(msg.value);

require(tokensToMint >= minPayout);
require(tokensToMint >= minPayout, "payout below requested minimum");

_weiPaid = _weiPaid.add(msg.value);
_mint(msg.sender, tokensToMint);
@@ -98,7 +98,7 @@ contract KosuToken is ERC20, Authorizable {
*/
function calculateEtherToToken(uint etherValue) internal view returns (uint) {
if (_weiPaid == 0 && totalSupply() == 0) {
require(etherValue == (2 ether)/10);
require(etherValue == (2 ether)/10, "first transaction must be .2 ether");
return 10000 ether;
} else {
return Formula.calculatePurchaseReturn(totalSupply(), _weiPaid, r, etherValue);
@@ -117,7 +117,7 @@ contract Treasury is Authorizable {
//Remove the system balance
setSystemBalance(account, getSystemBalance(account).sub(amount));
// Require the tokens being confiscated are only tokens already in kosu system contract control
require(getSystemBalance(account) >= getCurrentBalance(account));
require(getSystemBalance(account) >= getCurrentBalance(account), "system balance overburn");
}

/** @dev Allows accounts to be rewarded with tokens. These tokens were previously obtained by the calling contract and are now being redistributed to the provided account.
@@ -140,7 +140,7 @@ contract Treasury is Authorizable {
@param amount Number of tokens to burn.
*/
function burnFrom(address account, uint amount) isAuthorized public {
require(getCurrentBalance(account) >= amount);
require(getCurrentBalance(account) >= amount, "insufficient current balance");
kosuToken.burn(amount); //TODO: Consider event?
setCurrentBalance(account, getCurrentBalance(account).sub(amount));
setSystemBalance(account, getSystemBalance(account).sub(amount));
@@ -213,7 +213,7 @@ contract Treasury is Authorizable {
function _bond(address account) internal returns (uint) {
uint initialBalance = kosuToken.balanceOf(address(this));
uint minted = kosuToken.bondTokens.value(msg.value)(0);
require(initialBalance+minted == kosuToken.balanceOf(address(this)));
require(initialBalance + minted == kosuToken.balanceOf(address(this)), "tokens not minted");

setSystemBalance(account, getSystemBalance(account).add(minted));
setCurrentBalance(account, getCurrentBalance(account).add(minted));
@@ -234,7 +234,7 @@ contract Treasury is Authorizable {
*/
function _withdraw(address account, uint amount) internal {
//Sends tokens to the account reduce the values of internal and system balances by the value.
require(getCurrentBalance(account) >= amount);
require(getCurrentBalance(account) >= amount, "insufficient tokens");
require(kosuToken.transfer(account, amount));
setSystemBalance(account, getSystemBalance(account).sub(amount));
setCurrentBalance(account, getCurrentBalance(account).sub(amount));
@@ -207,7 +207,7 @@ contract ValidatorRegistry is Ownable {
*/
function registerListing(bytes32 tendermintPublicKey, uint tokensToStake, int rewardRate, string calldata details) external {
//tokensToStake must be greater than or equal to _minimumBalance
require(tokensToStake >= minimumBalance);
require(tokensToStake >= minimumBalance, "must register with at least minimum balance");

//Claim tokens from the treasury
treasury.claimTokens(msg.sender, tokensToStake);
@@ -216,9 +216,10 @@ contract ValidatorRegistry is Ownable {
Listing storage listing = _listings[tendermintPublicKey];

//Must not overwrite an existing listing
require(listing.status == Status.NULL);
require(listing.status == Status.NULL, "listing with public key exists");

if (rewardRate > 0) {
require(uint(rewardRate) <= maxRewardRate());
require(uint(rewardRate) <= maxRewardRate(), "reward rate exceeds max");
}

//Set listing values
@@ -247,7 +248,7 @@ contract ValidatorRegistry is Ownable {
Listing storage listing = _listings[tendermintPublicKey];

//Challenge pending and accepted listings. -- More valid status may be added.
require(listing.status == Status.PENDING || listing.status == Status.ACCEPTED || listing.status == Status.EXITING);
require(listing.status == Status.PENDING || listing.status == Status.ACCEPTED || listing.status == Status.EXITING, "listing is not pending, accepted or exiting");

//Ensure earns and burns are up to date return if a touch and remove was executed
_processRewards(listing);
@@ -289,10 +290,10 @@ contract ValidatorRegistry is Ownable {
Challenge storage challenge = _challenges[listing.currentChallenge];

//Must be currently challenged and after the end block but not finalized
require(listing.status == Status.CHALLENGED);
require(block.number > challenge.challengeEnd);
require(!challenge.finalized);
require(challenge.balance == listing.stakedBalance);
require(listing.status == Status.CHALLENGED, "listing is not challenged");
require(block.number > challenge.challengeEnd, "challenge has not ended");
require(!challenge.finalized, "challenge has been finalized");
require(challenge.balance == listing.stakedBalance, "challenge balance has changed");

uint winningOption = voting.winningOption(challenge.pollId);

@@ -357,9 +358,6 @@ contract ValidatorRegistry is Ownable {
listing.currentChallenge = 0;
_emitValidatorChallengeResolved(listing);
}

//ensure the ending state is correct
require(challenge.balance == challenge.voterTotal);
}
}

@@ -371,16 +369,13 @@ contract ValidatorRegistry is Ownable {
Challenge storage challenge = _challenges[challengeId];

//Must be after challenge period
require(block.number > challenge.challengeEnd);
require(block.number > challenge.challengeEnd, "challenge hasn't ended");

//Finalize the challenge
if (!challenge.finalized) {
resolveChallenge(challenge.listingKey);
}

//Ensure finalize has been completed
require(challenge.finalized);

//Get vote info
uint winningTokens = voting.userWinningTokens(challenge.pollId, msg.sender);
uint totalWinningTokens = voting.totalWinningTokens(challenge.pollId);
@@ -413,8 +408,9 @@ contract ValidatorRegistry is Ownable {
Listing storage listing = _listings[tendermintPublicKey];

//Must be called by owner after application period
require(listing.owner == msg.sender);
require(listing.status == Status.PENDING && listing.applicationBlock.add(applicationPeriod) <= block.number);
require(listing.owner == msg.sender, "not listing owner");
require(listing.status == Status.PENDING, "listing not pending");
require(listing.applicationBlock.add(applicationPeriod) <= block.number, "application period active");

//Listing is now accepted
listing.status = Status.ACCEPTED;
@@ -446,7 +442,7 @@ contract ValidatorRegistry is Ownable {
Listing storage listing = _listings[tendermintPublicKey];

//Listing owner must call this method
require(listing.owner == msg.sender);
require(listing.owner == msg.sender, "not listing owner");

//Exit immediately if the listing is still in pending status.
if (listing.status == Status.PENDING) {
@@ -461,7 +457,7 @@ contract ValidatorRegistry is Ownable {
}

//Ensure listing is in accepted
require(listing.status == Status.ACCEPTED);
require(listing.status == Status.ACCEPTED, "listing not accepted");

listing.status = Status.EXITING;
listing.exitBlock = block.number + exitPeriod;
@@ -479,11 +475,11 @@ contract ValidatorRegistry is Ownable {
Listing storage listing = _listings[tendermintPublicKey];

//Listing owner must call this method
require(listing.owner == msg.sender);
require(listing.owner == msg.sender, "not listing owner");

//The listing must be exiting and past the exit block challenge interrupts this process
require(listing.status == Status.EXITING);
require(listing.exitBlock <= block.number);
require(listing.status == Status.EXITING, "listing not exiting");
require(listing.exitBlock <= block.number, "exiting cool off period active");

//Approve and release tokens to treasury
kosuToken.approve(address(treasury), listing.stakedBalance);
@@ -503,15 +499,15 @@ contract ValidatorRegistry is Ownable {
Listing storage listing = _listings[tendermintPublicKey];

//Listing owner must call this method
require(listing.owner == msg.sender);
require(listing.owner == msg.sender, "not listing owner");
//Can only modify listing generating tokens
require(listing.rewardRate > 0);
require(listing.rewardRate > 0, "listing is not generating tokens");
//Can only reduce reward rate
require(listing.rewardRate > newRate);
require(listing.rewardRate > newRate, "not reducing reward rate");
//Must be below the maxRewardRate
require(uint(newRate) < maxRewardRate());
require(uint(newRate) < maxRewardRate(), "exceeds maximum reward rate");
//Listing must be active and in good standing.
require(listing.status == Status.ACCEPTED);
require(listing.status == Status.ACCEPTED, "listing is not accepted");

_processRewards(listing);
listing.rewardRate = newRate;
@@ -55,7 +55,7 @@ contract Voting {
*/
function createPoll(uint _commitEndBlock, uint _revealEndBlock) public returns (uint) {//TODO is it a concern that polls could be created by anyone freely?
// Reveal end after commit
require(_commitEndBlock < _revealEndBlock);
require(_commitEndBlock < _revealEndBlock, "commit must end before reveal");

// Set poll data
Poll storage p = polls[nextPollId];
@@ -91,10 +91,10 @@ contract Voting {
Vote storage v = p.votes[msg.sender];

//Ensure commit phase hasn't ended, the user has not committed and has adequate balance in the treasury
require(block.number <= p.commitEndBlock);
require(!p.didCommit[msg.sender]);
require(treasury.registerVote(msg.sender, _pollId, _tokensToCommit));
require(_tokensToCommit > 0);
require(block.number <= p.commitEndBlock, "commit has ended");
require(!p.didCommit[msg.sender], "address committed");
require(treasury.registerVote(msg.sender, _pollId, _tokensToCommit), "insufficient tokens");
require(_tokensToCommit > 0, "must commit tokens to lock");

//Set the tokens committed hidden vote data
v.tokensCommitted = _tokensToCommit;
@@ -115,15 +115,15 @@ contract Voting {
Vote storage v = p.votes[msg.sender];

// Ensure commit phase has passed, reveal phase has not. User has commited but not revealed. User has adequate balance in the treasury.
require(block.number > p.commitEndBlock);
require(block.number <= p.revealEndBlock);
require(p.didCommit[msg.sender]);
require(!p.didReveal[msg.sender]);
require(treasury.completeVote(msg.sender, _pollId));
require(block.number > p.commitEndBlock, "commit hasn't ended");
require(block.number <= p.revealEndBlock, "reveal has ended");
require(p.didCommit[msg.sender], "address hasn't committed");
require(!p.didReveal[msg.sender], "address has revealed");
require(treasury.completeVote(msg.sender, _pollId), "token's broke lock");

// Calculate and compare the commited vote
bytes32 exposedVote = keccak256(abi.encodePacked(_voteOption, _voteSalt));
require(v.hiddenVote == exposedVote);
require(v.hiddenVote == exposedVote, "vote doesn't match");

// Store info from a valid revealed vote. Remove the pending vote.
v.salt = _voteSalt;
@@ -146,7 +146,7 @@ contract Voting {
*/
function winningOption(uint _pollId) public view returns (uint) {
Poll memory p = polls[_pollId];
require(p.revealEndBlock < block.number);
require(p.revealEndBlock < block.number, "poll hasn't ended");
return p.currentLeadingOption;
}

@@ -156,7 +156,7 @@ contract Voting {
*/
function totalWinningTokens(uint _pollId) public view returns (uint) {
Poll memory p = polls[_pollId];
require(p.revealEndBlock < block.number);
require(p.revealEndBlock < block.number, "poll hasn't ended");
return p.leadingTokens;
}

@@ -166,7 +166,7 @@ contract Voting {
*/
function totalRevealedTokens(uint _pollId) public view returns (uint) {
Poll memory p = polls[_pollId];
require(p.revealEndBlock < block.number);
require(p.revealEndBlock < block.number, "poll hasn't ended");
return p.totalRevealedTokens;
}

@@ -176,7 +176,7 @@ contract Voting {
*/
function userWinningTokens(uint _pollId, address _user) public view returns (uint tokens) {
Poll memory p = polls[_pollId];
require(p.revealEndBlock < block.number);
require(p.revealEndBlock < block.number, "poll hasn't ended");
Vote memory v = polls[_pollId].votes[_user];

if(p.currentLeadingOption == v.voteOption) {
@@ -262,20 +262,17 @@ export class TestHelpers {
}

public async cleanAccounts(): Promise<void> {
const transactions = [];
for (const account of this.accounts) {
await this.clearTreasury(account);
if (account !== this.accounts[0]) {
await this.ensureTokenBalance(account, TestValues.zero);
}
transactions.push(
this.migratedContracts.kosuToken.approve.awaitTransactionSuccessAsync(
this.migratedContracts.treasury.address,
TestValues.zero,
{
from: account,
},
),
await this.migratedContracts.kosuToken.approve.awaitTransactionSuccessAsync(
this.migratedContracts.treasury.address,
TestValues.zero,
{
from: account,
},
);
}
}
@@ -125,6 +125,15 @@ describe("KosuToken", () => {
.toString()
.should.eq(endingEther.toString());
});

it("should fail with payout below minPayout", async () => {
const estimate = await kosuToken.estimateEtherToToken.callAsync(TestValues.oneEther);

await kosuToken.bondTokens
.callAsync(estimate.plus(TestValues.oneEther), { value: TestValues.oneEther })
.should.eventually.be.rejected.and.have.property("message")
.that.includes("payout below requested minimum");
});
});

describe("releaseTokens", () => {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.