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

For Issue #74 Test StakingRewards clone #139

Closed
wants to merge 9 commits into from
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: npm i
- run: npm ci

- save_cache:
paths:
Expand Down
2 changes: 1 addition & 1 deletion contracts/incentives/StakingRewards.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import "@daostack/arc/contracts/libs/SafeERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/math/Math.sol";
import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol";
import "../utils/ReentrancyGuard.sol";
import "./RewardDistributionRecipient.sol";


Expand Down
1 change: 0 additions & 1 deletion contracts/seed/Seed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ contract Seed {
} else if (fundingToken.balanceOf(address(this)) >= hardCap) {
maximumReached = true;
}

_addLock(
msg.sender,
(tokenLocks[msg.sender].seedAmount.add(_seedAmount)), // Previous Seed Amount + new seed amount
Expand Down
45 changes: 45 additions & 0 deletions contracts/utils/ReentrancyGuard.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
pragma solidity ^0.5.0;

/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* _Since v2.5.0:_ this module is now much more gas efficient, given net gas
* metering changes introduced in the Istanbul hardfork.
*/
contract ReentrancyGuard {
bool private _entered;

/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(!_entered, "ReentrancyGuard: reentrant call");

// Any calls to nonReentrant after this point will fail
_entered = true;

_;

// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_entered = false;
}
}
125 changes: 125 additions & 0 deletions test/staking-rewards-clone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*global artifacts, web3, contract, before, it, context*/
/*eslint no-undef: "error"*/

const { expect } = require('chai');
const { constants, /* time, */ expectRevert, expectEvent } = require('@openzeppelin/test-helpers');
const helpers = require('./helpers');

const StakingRewards = artifacts.require('StakingRewards');


const { toWei } = web3.utils;

const deploy = async (accounts) => {
// initialize test setup
const setup = await helpers.setup.initialize(accounts[0]);
// deploy ERC20s
setup.tokens = await helpers.setup.tokens(setup);
// deploy DAOStack meta-contracts
setup.DAOStack = await helpers.setup.DAOStack(setup);
// deploy organization
setup.organization = await helpers.setup.organization(setup);
// deploy balancer infrastructure
setup.balancer = await helpers.setup.balancer(setup);
// deploy token4rep
setup.token4rep = await helpers.setup.token4rep(setup);
// deploy incentives contract
setup.incentives = await helpers.setup.incentives(setup);
// deploy seedFactory
setup.seedFactory = await helpers.setup.seedFactory(setup);
// deploy farmFactory
setup.farmFactory = await helpers.setup.farmFactory(setup);
// deploy primeDAO governance
setup.primeDAO = await helpers.setup.primeDAO(setup);

return setup;
};

const deployStakingClone = async (setup, stakingOptions) => {
const calldata = helpers.encodeCreateFarm(...stakingOptions);
const _tx = await setup.primeDAO.farmManager.proposeCalls([setup.farmFactory.address],[calldata], [0], constants.ZERO_BYTES32);
const proposalId = helpers.getNewProposalId(_tx);
await setup.primeDAO.farmManager.voting.absoluteVote.vote(proposalId, 1, 0, constants.ZERO_ADDRESS);
const tx = await setup.primeDAO.farmManager.execute(proposalId);
setup.data.tx = tx;
const receipt = await expectEvent.inTransaction(setup.data.tx.tx, setup.farmFactory, 'FarmCreated', {});
const contract = await StakingRewards.at(receipt.args[0]);
return contract;
};

contract('StakingRewards Clone', (accounts) => {
let setup;
// let stakeAmount;
// let halfStake;
// let rewardAmount;
let _name = 'newFarm';
// let rescueAmount = toWei('100');
// let stakingAmount = toWei('100');
let _initreward = toWei('9249.999999999999475712');
// let _badInitReward;
let _starttime = 1600560000; // 2020-09-20 00:00:00 (UTC +00:00)
let _durationDays = 7;
// let initTime;
let rewardToken;
let stakingToken;
// let rescueToken;

before('!! deploy setup', async () => {
setup = await deploy(accounts);
});

context('» clone contract is initialized ', async () => {
before('!! deploy clone', async () => {
[rewardToken, stakingToken] = await setup.tokens.erc20s;
await rewardToken.transfer(setup.organization.avatar.address, _initreward);
const stakingOptions = [_name, rewardToken.address, stakingToken.address, _initreward, _starttime, _durationDays, setup.organization.avatar.address];
setup.incentives.stakingRewards = await deployStakingClone(setup, stakingOptions);
await setup.tokens.primeToken.transfer(setup.incentives.stakingRewards.address, _initreward);
});
context('» reverts when initialise is called', () => {
it('it cannot initializes contract', async () => {
await expectRevert(setup.incentives.stakingRewards.initialize(_name, setup.tokens.primeToken.address, setup.balancer.pool.address, _starttime, _durationDays, setup.organization.avatar.address),
'StakingRewards: contract already initialized');
});
});
context('» initialised correctly', async () => {
it('correct total rewards', async () => {
const totalSupply = await setup.incentives.stakingRewards.totalRewards();
expect(totalSupply.toString()).to.equal(_initreward);
});
it('correct start time', async () => {
const startTime = await setup.incentives.stakingRewards.starttime();
expect(startTime.toString()).to.equal(_starttime.toString());
});
it('correct duration', async () => {
const duration = await setup.incentives.stakingRewards.duration();
expect(duration.toString()).to.equal((_durationDays*24*60*60).toString());
});
it('lastUpdateTime == startTime', async () => {
const lastUpdateTime = await setup.incentives.stakingRewards.lastUpdateTime();
expect(lastUpdateTime.toString()).to.equal(_starttime.toString());
});
});
});
context('# stake', async () => {
before('!! deploy clone', async () => {
setup = await deploy(accounts);
// stakeAmount = toWei('100');
});
context('stake parameter is not valid', async () => {
before('!! deploy clone and fund', async () => {
[rewardToken, stakingToken] = await setup.tokens.erc20s;
await rewardToken.transfer(setup.organization.avatar.address, _initreward);
const stakingOptions = [_name, rewardToken.address, stakingToken.address, _initreward, _starttime, _durationDays, setup.organization.avatar.address];
setup.incentives.stakingRewards = await deployStakingClone(setup, stakingOptions);
await setup.tokens.primeToken.transfer(setup.incentives.stakingRewards.address, _initreward);
});
it('it reverts', async () => {
await expectRevert(
setup.incentives.stakingRewards.stake(toWei('0')),
'StakingRewards: cannot stake 0'
);
});
});
});
});
2 changes: 1 addition & 1 deletion test/staking-rewards.js
Original file line number Diff line number Diff line change
Expand Up @@ -730,4 +730,4 @@ contract('StakingRewards', (accounts) => {
});
});
});
});
});