Skip to content

Commit a1e6839

Browse files
committed
test(functional): user and owner interactions. refactored to rely mostly on buidler
1 parent d389060 commit a1e6839

File tree

6 files changed

+190
-62
lines changed

6 files changed

+190
-62
lines changed

buidler.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import "./tasks/clean";
99
import "./tasks/typechain";
1010

1111
usePlugin("@nomiclabs/buidler-waffle");
12+
usePlugin("@nomiclabs/buidler-ethers");
1213
usePlugin("solidity-coverage");
1314

1415
interface HDAccountsConfigExtended extends HDAccountsConfig {

contracts/SinglePlayerCommit.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import "@openzeppelin/contracts/access/Ownable.sol";
77
import "@openzeppelin/contracts/math/SafeMath.sol";
88
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
99

10+
//TODO Activity deployed in test now only has name/oracle/allowed initialized
11+
//TODO Do we want console.log logging by buidler? Which level?
12+
1013
contract SinglePlayerCommit is Ownable {
1114
using SafeMath for uint256;
1215

@@ -24,7 +27,6 @@ contract SinglePlayerCommit is Ownable {
2427
bool allowed;
2528
}
2629

27-
//TODO Activity deployed in test now only has name/oracle/allowed initialized
2830
struct Activity {
2931
string name; // e.g. "cycling"
3032
bytes32[] measures; // keys from allowedMeasures
Lines changed: 142 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,163 @@
1-
import { ethers } from "@nomiclabs/buidler";
21
import { expect } from "chai";
3-
import { MockProvider } from "ethereum-waffle";
4-
import { Wallet, utils } from "ethers";
5-
import { BytesLike } from "ethers/lib/utils";
2+
import { ethers } from "@nomiclabs/buidler";
3+
import { Signer, utils, BigNumber, BytesLike } from "ethers";
64
import { SinglePlayerCommit } from "../typechain/SinglePlayerCommit";
5+
import { DH_UNABLE_TO_CHECK_GENERATOR } from "constants";
76

8-
export function shouldManageCommitments(provider: MockProvider): void {
9-
const [contractWallet, userWallet] = provider.getWallets();
7+
//TODO Check for emitted events
8+
export function shouldManageCommitments(): void {
9+
context("User can", function () {
10+
let owner: Signer;
11+
let user: Signer;
12+
let contractWithUser: SinglePlayerCommit;
13+
const _overrides = {
14+
gasLimit: 1000000,
15+
};
16+
17+
before(async function () {
18+
[owner, user] = await ethers.getSigners();
19+
contractWithUser = await this.singlePlayerCommit.connect(user);
20+
});
1021

11-
context('user can', function () {
1222
it("deposit funds for staking", async function () {
13-
const contract = this.singlePlayerCommit;
23+
//User balance
24+
const _userBalance: BigNumber = await user.getBalance();
25+
expect(_userBalance).to.equal(utils.parseEther("10000.0"));
1426

15-
const contractWithUser = await contract.connect(userWallet);
16-
console.log("Connected to contract with wallet: " + userWallet.address)
27+
//Committer balance
28+
const _committerBalance: BigNumber = await this.singlePlayerCommit.committerBalance();
29+
expect(_committerBalance).to.equal(utils.parseEther("0.0"));
1730

18-
const _amountToDeposit = utils.parseEther("1.0");
19-
const _overrides = {
20-
gasLimit: 100000,
21-
};
31+
//Transaction
32+
const _amountToDeposit: BigNumber = utils.parseEther("1.0");
2233

23-
//TODO Error: revert Mock on the method is not initialized
24-
expect(await contractWithUser.deposit(_amountToDeposit, _overrides)).to.equal(true);
25-
console.log('deposited funds')
34+
await this.token.mock.transferFrom.returns(true);
35+
await contractWithUser.deposit(_amountToDeposit, _overrides);
2636

27-
const _committerBalance = await contract.committerBalance.call();
28-
console.log(_committerBalance);
37+
//Validate
38+
const _updatedUserBalance: BigNumber = await user.getBalance();
39+
const _updatedCommitterBalance: BigNumber = await this.singlePlayerCommit.committerBalance.call();
40+
const _userBalanceInContract: BigNumber = await this.singlePlayerCommit.balances(user.getAddress());
2941

30-
expect(_committerBalance).to.equal(_amountToDeposit)
31-
expect('_deposit').to.be.calledOnContract(contract);
32-
expect('_changeCommitterBalance').to.be.calledOnContract(contract);
42+
expect(_userBalanceInContract.eq(_amountToDeposit)).to.be.true;
43+
expect(_updatedCommitterBalance.eq(_amountToDeposit)).to.be.true;
44+
expect(_updatedUserBalance.lt(_userBalance));
3345
});
3446

35-
it.skip('withdraw deposited funds', async function () {
36-
expect(1).to.equal(1);
47+
it("withdraw deposited funds", async function () {
48+
//User balance
49+
const _userBalance: BigNumber = await user.getBalance();
50+
expect(_userBalance.lt(utils.parseEther("10000.0"))).to.be.true;
51+
52+
//Committer balance
53+
const _committerBalance: BigNumber = await this.singlePlayerCommit.committerBalance();
54+
expect(_committerBalance).to.equal(utils.parseEther("1.0"));
55+
56+
//Transaction
57+
const _amountToWithdraw: BigNumber = utils.parseEther("1.0");
58+
59+
await this.token.mock.transfer.returns(true);
60+
await contractWithUser.withdraw(_amountToWithdraw, _overrides);
61+
62+
//Validate
63+
const _updatedUserBalance: BigNumber = await user.getBalance();
64+
const _updatedCommitterBalance: BigNumber = await this.singlePlayerCommit.committerBalance.call();
65+
const _userBalanceInContract: BigNumber = await this.singlePlayerCommit.balances(user.getAddress());
66+
67+
expect(_userBalanceInContract.isZero()).to.be.true;
68+
expect(_updatedCommitterBalance.isZero()).to.be.true;
69+
expect(_updatedUserBalance.gt(_userBalance));
3770
});
3871

39-
it.skip("make a commitment of biking 50 kms against stake with deposited funds", async function () {
40-
// const _activity = "biking";
41-
// const _measureIndex = await this.singlePlayerCommit.measureList(0);
42-
const contractWithSigner = await this.singlePlayerCommit.connect(userWallet);
72+
it("make a commitment of biking 50 kms against 1ETH stake with deposited funds", async function () {
73+
//Deposit funds
74+
const _amountToDeposit: BigNumber = utils.parseEther("1.0");
75+
await this.token.mock.transferFrom.returns(true);
76+
await contractWithUser.deposit(_amountToDeposit, _overrides);
4377

44-
console.log(await userWallet.getBalance());
45-
const _activity = await this.singlePlayerCommit.activityList(0);
46-
const _measureIndex = 0
47-
const _goal = 50;
48-
const _startTime = Date.now();
49-
const _stake = 10;
50-
await contractWithSigner.makeCommitment(_activity, _measureIndex, _goal, _startTime, _stake);
78+
//User balance in contract
79+
const _userBalance: BigNumber = await this.singlePlayerCommit.balances(user.getAddress());
80+
expect(_userBalance.eq(utils.parseEther('1.0'))).to.be.true;
81+
82+
//Committer balance in contract
83+
expect(await this.singlePlayerCommit.committerBalance()).to.equal(utils.parseEther('1.0'));
84+
85+
//Transaction
86+
const _activity: BytesLike = await this.singlePlayerCommit.activityList(0);
87+
const _measureIndex: number = 0;
88+
const _goal: number = 50;
89+
const _startTime: number = Date.now();
90+
91+
const _amountToStake: BigNumber = utils.parseEther('1.0');
92+
93+
await this.token.mock.transfer.returns(true);
94+
await contractWithUser.makeCommitment(_activity, _measureIndex, _goal, _startTime, _amountToStake, _overrides);
95+
96+
//Commitment
97+
const commitment = await this.singlePlayerCommit.commitments(user.getAddress());
98+
99+
//Validate
100+
expect(commitment.committer).to.be.properAddress;
101+
expect(await this.singlePlayerCommit.getActivityName(commitment.activity)).to.equal('biking')
102+
expect(await this.singlePlayerCommit.getMeasureName(commitment.measure)).to.equal('km')
103+
expect(commitment.goalValue.toNumber()).to.equal(_goal)
104+
expect(commitment.stake).to.equal(_amountToStake)
105+
expect(commitment.start).to.equal(_startTime)
106+
107+
//TODO Check 7 days in future
108+
// const _endTime = new Date().setDate(_startTime + 7)
109+
// console.log(_endTime)
110+
// expect(commitment.start).to.equal(utils.bigNumberify())
51111

52-
expect(1).to.equal(1);
53112
});
113+
114+
it("make a deposit and commitment of biking 50 kms against 1ETH stake with deposited funds in a single call", async function () {
115+
expect(1).to.equal(1)
54116
});
55117

118+
context("Owner can", function () {
119+
let owner: Signer;
120+
let user: Signer;
121+
let contractWithOwner: SinglePlayerCommit;
122+
const _overrides = {
123+
gasLimit: 1000000,
124+
};
125+
126+
before(async function () {
127+
[owner, user] = await ethers.getSigners();
128+
contractWithOwner = await this.singlePlayerCommit.connect(owner);
129+
});
130+
131+
it("withdraw non-committed balance", async function () {
132+
//Owner balance
133+
const _ownerBalance: BigNumber = await owner.getBalance();
134+
console.log("Owner balance: ", utils.formatEther(_ownerBalance))
135+
136+
//Committer balance
137+
const _committerBalance: BigNumber = await this.singlePlayerCommit.committerBalance();
138+
console.log("Committer balance: ", utils.formatEther(_committerBalance))
139+
expect(_committerBalance).to.equal(utils.parseEther('1.0'));
140+
141+
//Contract balance
142+
const margin = utils.parseEther('10');
143+
await this.token.mock.balanceOf.returns(_committerBalance.add(margin))
56144

145+
const _contractBalance: BigNumber = await this.token.balanceOf(contractWithOwner.address);
146+
console.log("Contract balance: ", utils.formatEther(_contractBalance))
147+
148+
//Transaction
149+
await this.token.mock.transfer.returns(true)
150+
await contractWithOwner.ownerWithdraw(10, _overrides);
151+
152+
//Validate
153+
const _updatedOwnerBalance: BigNumber = await owner.getBalance();
154+
const _updatedCommitterBalance: BigNumber = await this.singlePlayerCommit.committerBalance.call();
155+
156+
expect(1).to.equal(1);
157+
158+
// expect(_updatedOwnerBalance.gt(_ownerBalance)).to.be.true;
159+
// expect(_updatedCommitterBalance.lt(_committerBalance)).to.be.true;
160+
});
161+
});
162+
})
57163
}

test/SinglePlayerCommit.deploy.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { expect } from "chai";
22
import { BytesLike } from "ethers/lib/utils";
3-
import { SinglePlayerCommit } from "../typechain/SinglePlayerCommit";
3+
4+
//TODO Need provider that has a state/memory for check on contract calls (function().to.be.calledOnContract()). Like the one from Waffle?
5+
//Example expect('_deposit').to.be.calledOnContract(this.singlePlayerCommit);
6+
//TODO Now expecting VM Runtime 'invalid opcode' error.
7+
// Should/can this be prevented in contract while using dynamic arrays? Look at revert()
48

59
export function shouldDeployWithInitialParameters(): void {
610

@@ -16,20 +20,17 @@ export function shouldDeployWithInitialParameters(): void {
1620
// expect(_activity['ranges']).to.equal([2,1024]);
1721
expect(_activity['oracle']).to.be.properAddress;
1822
expect(_activity['allowed']).to.be.true;
19-
expect('getActivityName').to.be.calledOnContract(this.singlePlayerCommit);
23+
// expect('getActivityName').to.be.calledOnContract(this.singlePlayerCommit);
2024
});
2125

22-
//TODO Now expecting VM Runtime 'invalid opcode' error.
23-
// Should/can this be prevented in contract while using dynamic arrays?
2426
it("has no other activities", async function () {
2527
let error;
2628
try{
2729
await this.singlePlayerCommit.activityList(1)
2830
} catch(err) {
2931
error = err;
3032
} finally {
31-
expect('activityList').to.be.calledOnContract(this.singlePlayerCommit);
32-
expect(error.results[error.hashes[0]]['error']).to.equal('invalid opcode');
33+
expect(error.message).to.equal('Transaction reverted without a reason');
3334
}
3435
});
3536

@@ -49,8 +50,7 @@ export function shouldDeployWithInitialParameters(): void {
4950
} catch(err) {
5051
error = err;
5152
} finally {
52-
expect('measureList').to.be.calledOnContract(this.singlePlayerCommit);
53-
expect(error.results[error.hashes[0]]['error']).to.equal('invalid opcode');
53+
expect(error.message).to.equal('Transaction reverted without a reason');
5454
}
5555
});
5656

test/SinglePlayerCommit.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,60 @@
1+
//Setup
12
import chai from "chai";
2-
import { MockProvider, deployContract, deployMockContract, solidity } from "ethereum-waffle";
3+
import { ethers } from "@nomiclabs/buidler";
4+
import { BigNumberish, Signer, ContractFactory } from "ethers";
5+
import { deployMockContract, MockContract, solidity } from "ethereum-waffle";
36

4-
import SPCommitArtifact from "../artifacts/SinglePlayerCommit.json";
7+
//Artifacts
8+
import { SinglePlayerCommit } from "../typechain/SinglePlayerCommit";
59
import daiArtifact from "./resources/DAI.json";
610
import chainLinkArtifact from "./resources/ChainLink.json";
711

8-
import { SinglePlayerCommit } from "../typechain/SinglePlayerCommit";
9-
import { BigNumberish } from "ethers";
12+
//Test suites
1013
import { shouldDeployWithInitialParameters } from "./SinglePlayerCommit.deploy";
11-
import { shouldManageCommitments } from './SinglePlayerCommit.commitment';
14+
import { shouldManageCommitments } from "./SinglePlayerCommit.commitment";
1215

1316
chai.use(solidity);
1417

1518
setTimeout(async function () {
16-
describe("SinglePlayerCommit contract", function () {
17-
const provider: MockProvider = new MockProvider()
18-
const [wallet, walletTo] = provider.getWallets();
19+
describe("SinglePlayerCommit contract", async function () {
20+
let accounts: Signer[];
21+
let owner: Signer;
1922
const activity: string = "biking";
2023
const measures: string[] = ["km"];
2124
const ranges: BigNumberish[][] = [[2, 1024]];
2225

2326
before(async function () {
24-
console.log("Setting up mock objects");
25-
const mockChainLink = await deployMockContract(wallet, chainLinkArtifact);
26-
const mockDAI = await deployMockContract(wallet, daiArtifact);
27+
console.log("Getting accounts");
28+
accounts = await ethers.getSigners();
29+
owner = accounts[0];
30+
console.log("Owner set to ", await owner.getAddress());
31+
32+
console.log("Setting up mock objects for ChainLink and DAI");
33+
this.oracle = await deployMockContract(owner, chainLinkArtifact) as MockContract;
34+
this.token = await deployMockContract(owner, daiArtifact) as MockContract;
2735

28-
console.log("Deploying SPCommit with an activity, measures, and ranges");
29-
this.singlePlayerCommit = (await deployContract(wallet, SPCommitArtifact, [
36+
console.log("Deploying SPCommit with %s, %s, and %s", activity, measures, ranges[0]);
37+
const SinglePlayerCommit: ContractFactory = await ethers.getContractFactory("SinglePlayerCommit");
38+
39+
this.singlePlayerCommit = (await SinglePlayerCommit.deploy(
3040
activity,
3141
measures,
3242
ranges,
33-
mockChainLink.address,
34-
mockDAI.address,
35-
])) as SinglePlayerCommit;
43+
this.oracle.address,
44+
this.token.address,
45+
)) as SinglePlayerCommit;
46+
await this.singlePlayerCommit.deployed();
47+
48+
console.log("SinglePlayerCommit contract deployed to ", this.singlePlayerCommit.address);
49+
3650
});
3751

3852
describe("Deployment was succesful if contract", function () {
3953
shouldDeployWithInitialParameters();
4054
});
4155

4256
describe("Commitments can be managed", function () {
43-
shouldManageCommitments(provider);
57+
shouldManageCommitments();
4458
});
4559
});
4660

tsconfig.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,10 @@
2323
"test/**/*",
2424
"typechain/**/*",
2525
"buidler.config.ts"
26+
],
27+
"files": [
28+
"./buidler.config.ts",
29+
"./node_modules/@nomiclabs/buidler-ethers/src/type-extensions.d.ts",
30+
"./node_modules/@nomiclabs/buidler-waffle/src/type-extensions.d.ts"
2631
]
2732
}

0 commit comments

Comments
 (0)