Permalink
Browse files

Merge pull request #22 from aragon/coverage100

Increase test coverage
  • Loading branch information...
izqui committed Nov 14, 2017
2 parents ab33dfa + 8190c4f commit 49253097831a6f979c68c309ae0c6c00c325af4d
@@ -116,6 +116,15 @@ contract('Finance App', accounts => {
assert.equal(await token2.balanceOf(recipient), 190, 'recipient should have received tokens')
})

it('can change period duration', async () => {
await app.setPeriodDuration(50)
await app.mock_setTimestamp(160) // previous period duration was 100, so at time 160 must have transitioned 2 periods

await app.tryTransitionAccountingPeriod(5) // transition a maximum of 5 accounting periods

assert.equal(await app.currentPeriodId(), 2, 'should have transitioned 2 periods')
})

context('setting budget', () => {
const recipient = accounts[1]
const time = 22
@@ -134,7 +134,7 @@ contract Fundraising is App, Initializable, ERC677Receiver {
uint256 returnTokens = _buy(_saleId, msg.sender, _payedTokens);

// No need to return tokens as we never take them from sender's balance
assert(raisedToken.transferFrom(msg.sender, vault, _payedTokens.sub(returnTokens)));
require(raisedToken.transferFrom(msg.sender, vault, _payedTokens.sub(returnTokens)));
}

/**
@@ -149,9 +149,9 @@ contract Fundraising is App, Initializable, ERC677Receiver {

uint256 returnTokens = _buy(saleId, _sender, _value);

assert(raisedToken.transfer(vault, _value.sub(returnTokens)));
require(raisedToken.transfer(vault, _value.sub(returnTokens)));
if (returnTokens > 0)
assert(raisedToken.transfer(_sender, returnTokens));
require(raisedToken.transfer(_sender, returnTokens));

return true;
}
@@ -298,7 +298,7 @@ contract Fundraising is App, Initializable, ERC677Receiver {
isInversePrice = sale.isInversePrice;
price = period.initialPrice.mul(pricePrecision);

if (period.finalPrice != 0) { // interpolate price by period
if (period.initialPrice != period.finalPrice) { // interpolate price by period
uint256 periodDelta = uint256(period.periodEnds).sub(uint256(sale.periodStartTime));
uint256 periodState = getTimestamp().sub(uint256(sale.periodStartTime));
if (period.finalPrice > period.initialPrice) {
@@ -341,5 +341,7 @@ contract Fundraising is App, Initializable, ERC677Receiver {
}
}

function getTimestamp() internal constant returns (uint256) { return now; }
function getTimestamp() internal constant returns (uint256) {
return now;
}
}
@@ -117,6 +117,15 @@ contract('Fundraising', accounts => {
})
})

it('supports increasing price sales', async () => {
await fundraising.newSale(zeroAddress, raisedToken.address, 10000, 10000, 0, false, 1, [11], [2, 4])
await fundraising.mock_setTimestamp(6)
const [price, inverse, precision] = await fundraising.getCurrentPrice(0)

assert.equal(price, 3 * precision, 'price and precision should be correct')
assert.isFalse(inverse, 'price should be inverse')
})

context('ERC677 sales', () => {
let etherToken, buyData = {}

@@ -128,6 +137,12 @@ contract('Fundraising', accounts => {
buyData = fundraising.contract.buyWithToken.getData(saleId)
})

it('fails when calling buy with token externally', async () => {
return assertInvalidOpcode(async () => {
console.log(await fundraising.buyWithToken(0))
})
})

it('buys tokens correctly', async () => {
await etherToken.wrapAndCall(fundraising.address, buyData, { value: 100 }) // performs transferAndCall under the hood

@@ -155,6 +170,12 @@ contract('Fundraising', accounts => {
await etherToken.wrapAndCall(fundraising.address, fundraising.contract.buyWithToken.getData(100), { value: 15000 })
})
})

it('fails if not buying through token', async () => {
return assertInvalidOpcode(async () => {
await fundraising.tokenFallback(accounts[1], 100, buyData)
})
})
})

context('creating normal rate sale', () => {
@@ -205,6 +226,17 @@ contract('Fundraising', accounts => {
})
})

it('fails if buying with more tokens than owned', async () => {
await fundraising.mock_setTimestamp(11)

// transfers all its tokens away before buying
await raisedToken.transfer(accounts[7], 1000, { from: holder1000 })

return assertInvalidOpcode(async () => {
await fundraising.transferAndBuy(0, 110, { from: holder1000 })
})
})

it('can only buy up-to max raised', async () => {
await fundraising.mock_setTimestamp(11)

@@ -237,6 +269,21 @@ contract('Fundraising', accounts => {
assert.isTrue(closed, 'sale should be closed')
})

it('fails if buying in closed sale', async () => {
await fundraising.forceCloseSale(0)

return assertInvalidOpcode(async () => {
await fundraising.transferAndBuy(0, 90, { from: holder1000 })
})
})

it('fails if closing closed sale', async () => {
await fundraising.forceCloseSale(0)
return assertInvalidOpcode(async () => {
await fundraising.forceCloseSale(0)
})
})

it('can close sale after all periods ended', async () => {
await fundraising.mock_setTimestamp(32)
await fundraising.closeSale(0)
@@ -97,7 +97,7 @@ contract TokenManager is App, Initializable, TokenController, EVMCallScriptRunne
* @param _amount Number of tokens wrapped
*/
function wrap(uint256 _amount) onlyWrapper external {
assert(wrappedToken.transferFrom(msg.sender, address(this), _amount));
require(wrappedToken.transferFrom(msg.sender, address(this), _amount));
_mint(msg.sender, _amount);
}

@@ -108,7 +108,7 @@ contract TokenManager is App, Initializable, TokenController, EVMCallScriptRunne
function unwrap(uint256 _amount) onlyWrapper external {
require(transferrableBalance(msg.sender, now) >= _amount);
_burn(msg.sender, _amount);
assert(wrappedToken.transfer(msg.sender, _amount));
require(wrappedToken.transfer(msg.sender, _amount));
}

/**
@@ -180,7 +180,7 @@ contract TokenManager is App, Initializable, TokenController, EVMCallScriptRunne

// transferFrom always works as controller
// onTransfer hook always allows if transfering to token controller
assert(token.transferFrom(_holder, address(this), nonVested));
require(token.transferFrom(_holder, address(this), nonVested));

RevokeVesting(_holder, _vestingId);
}
@@ -287,15 +287,15 @@ contract TokenManager is App, Initializable, TokenController, EVMCallScriptRunne
}

function _assign(address _receiver, uint256 _amount) internal {
assert(token.transfer(_receiver, _amount));
require(token.transfer(_receiver, _amount));
}

function _burn(address _holder, uint256 _amount) internal {
assert(token.destroyTokens(_holder, _amount));
token.destroyTokens(_holder, _amount); // minime.destroyTokens() never returns false
}

function _mint(address _receiver, uint256 _amount) internal {
assert(token.generateTokens(_receiver, _amount));
token.generateTokens(_receiver, _amount); // minime.generateTokens() never returns false
}

/**
@@ -304,7 +304,9 @@ contract TokenManager is App, Initializable, TokenController, EVMCallScriptRunne
* @return True if the ether is accepted, false for it to throw
*/
function proxyPayment(address _owner) payable returns (bool) {
revert();
// Even though it is tested, solidity-coverage doesnt get it because
// MiniMeToken is not instrumented and entire tx is reverted
require(msg.sender == address(token));
_owner;
return false;
}
@@ -25,6 +25,12 @@ contract('Token Manager', accounts => {
})
})

it('fails when sending ether to token', async () => {
return assertInvalidOpcode(async () => {
await token.send(1) // transfer 1 wei to token contract
})
})

context('for native tokens', () => {
const holder = accounts[1]

@@ -59,6 +65,14 @@ contract('Token Manager', accounts => {
assert.equal(await token.balanceOf(tokenManager.address), 0, 'token manager should have 0 tokens')
})

it('cannot assign more tokens than owned', async () => {
await tokenManager.issue(50)

return assertInvalidOpcode(async () => {
await tokenManager.assign(holder, 51)
})
})

it('cannot wrap tokens', async () => {
return assertInvalidOpcode(async () => {
await tokenManager.wrap(100, { from: holder })
@@ -119,7 +133,7 @@ contract('Token Manager', accounts => {
})

it('can transfer half mid vesting', async () => {
await timetravel(3000)
await timetravel(start + (vesting - start) / 2)

await token.transfer(accounts[2], 20, { from: holder })

@@ -132,6 +146,14 @@ contract('Token Manager', accounts => {
})
})

it('can approve non-vested tokens but transferFrom fails', async () => {
await token.approve(accounts[2], 10, { from: holder })

return assertInvalidOpcode(async () => {
await token.transferFrom(holder, accounts[2], 10, { from: accounts[2] })
})
})

it('cannot transfer all tokens right before vesting', async () => {
await timetravel(vesting - 10)
return assertInvalidOpcode(async () => {
@@ -242,6 +264,16 @@ contract('Token Manager', accounts => {
await tokenManager.unwrap(100, { from: holder100 })
})
})

it('fails if unwrapping more tokens than token managers balance', async () => {
// after being wrapped, as token controller we can move tokens at our will
// this scenario shouldn't happen in reality, as wrapped tokens should be
// trustless tokens in which this operation is not allowed
await wrappedToken.transferFrom(tokenManager.address, accounts[7], 100)
return assertInvalidOpcode(async () => {
await tokenManager.unwrap(100, { from: holder100 })
})
})
})
})
})

0 comments on commit 4925309

Please sign in to comment.