Skip to content
This repository was archived by the owner on May 22, 2023. It is now read-only.

Commit 3c68bf2

Browse files
committed
Added tests for ETH bonding and staking contracts
1 parent 00aebb4 commit 3c68bf2

File tree

2 files changed

+284
-0
lines changed

2 files changed

+284
-0
lines changed

solidity/test/ETHBondingTest.js

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
const {accounts, contract, web3} = require("@openzeppelin/test-environment")
2+
const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot")
3+
4+
const KeepRegistry = contract.fromArtifact("KeepRegistry")
5+
const ETHStaking = contract.fromArtifact("ETHStaking")
6+
const ETHBonding = contract.fromArtifact("ETHBonding")
7+
const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver")
8+
9+
const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers")
10+
11+
const BN = web3.utils.BN
12+
13+
const chai = require("chai")
14+
chai.use(require("bn-chai")(BN))
15+
const expect = chai.expect
16+
17+
describe("ETHBonding", function () {
18+
let registry
19+
let ethStaking
20+
let ethBonding
21+
let etherReceiver
22+
23+
let operator
24+
let authorizer
25+
let beneficiary
26+
let stakeOwner
27+
let bondCreator
28+
let sortitionPool
29+
30+
before(async () => {
31+
operator = accounts[1]
32+
authorizer = accounts[2]
33+
beneficiary = accounts[3]
34+
stakeOwner = accounts[4]
35+
bondCreator = accounts[5]
36+
sortitionPool = accounts[6]
37+
38+
registry = await KeepRegistry.new()
39+
ethStaking = await ETHStaking.new(registry.address)
40+
ethBonding = await ETHBonding.new(registry.address, ethStaking.address)
41+
etherReceiver = await TestEtherReceiver.new()
42+
43+
await registry.approveOperatorContract(bondCreator)
44+
45+
await ethStaking.stake(operator, beneficiary, authorizer, {
46+
from: stakeOwner,
47+
})
48+
49+
await ethStaking.authorizeOperatorContract(operator, bondCreator, {
50+
from: authorizer,
51+
})
52+
})
53+
54+
beforeEach(async () => {
55+
await createSnapshot()
56+
})
57+
58+
afterEach(async () => {
59+
await restoreSnapshot()
60+
})
61+
62+
describe("withdraw", async () => {
63+
const value = new BN(1000)
64+
65+
beforeEach(async () => {
66+
await ethBonding.deposit(operator, {value: value})
67+
})
68+
69+
it("can be called by operator", async () => {
70+
await ethBonding.withdraw(value, operator, {from: operator})
71+
// ok, no reverts
72+
})
73+
74+
it("can be called by stake owner", async () => {
75+
await ethBonding.withdraw(value, operator, {from: stakeOwner})
76+
// ok, no reverts
77+
})
78+
79+
it("cannot be called by authorizer", async () => {
80+
await expectRevert(
81+
ethBonding.withdraw(value, operator, {from: authorizer}),
82+
"Only operator or the owner is allowed to withdraw bond"
83+
)
84+
})
85+
86+
it("cannot be called by beneficiary", async () => {
87+
await expectRevert(
88+
ethBonding.withdraw(value, operator, {from: beneficiary}),
89+
"Only operator or the owner is allowed to withdraw bond"
90+
)
91+
})
92+
93+
it("cannot be called by third party", async () => {
94+
const thirdParty = accounts[7]
95+
96+
await expectRevert(
97+
ethBonding.withdraw(value, operator, {from: thirdParty}),
98+
"Only operator or the owner is allowed to withdraw bond"
99+
)
100+
})
101+
102+
it("transfers unbonded value to beneficiary", async () => {
103+
const expectedUnbonded = 0
104+
105+
const expectedBeneficiaryBalance = web3.utils
106+
.toBN(await web3.eth.getBalance(beneficiary))
107+
.add(value)
108+
109+
await ethBonding.withdraw(value, operator, {from: operator})
110+
111+
const unbonded = await ethBonding.availableUnbondedValue(
112+
operator,
113+
bondCreator,
114+
sortitionPool
115+
)
116+
expect(unbonded).to.eq.BN(expectedUnbonded, "invalid unbonded value")
117+
118+
const actualBeneficiaryBalance = await web3.eth.getBalance(beneficiary)
119+
expect(actualBeneficiaryBalance).to.eq.BN(
120+
expectedBeneficiaryBalance,
121+
"invalid beneficiary balance"
122+
)
123+
})
124+
125+
it("emits event", async () => {
126+
const value = new BN(90)
127+
128+
const receipt = await ethBonding.withdraw(value, operator, {
129+
from: operator,
130+
})
131+
expectEvent(receipt, "UnbondedValueWithdrawn", {
132+
operator: operator,
133+
beneficiary: beneficiary,
134+
amount: value,
135+
})
136+
})
137+
138+
it("reverts if insufficient unbonded value", async () => {
139+
const invalidValue = value.add(new BN(1))
140+
141+
await expectRevert(
142+
ethBonding.withdraw(invalidValue, operator, {from: operator}),
143+
"Insufficient unbonded value"
144+
)
145+
})
146+
147+
it("reverts if transfer fails", async () => {
148+
const operator2 = accounts[7]
149+
150+
await etherReceiver.setShouldFail(true)
151+
152+
await ethStaking.stake(operator2, etherReceiver.address, authorizer, {
153+
from: stakeOwner,
154+
})
155+
156+
await ethBonding.deposit(operator2, {value: value})
157+
158+
await expectRevert(
159+
ethBonding.withdraw(value, operator2, {from: operator2}),
160+
"Transfer failed"
161+
)
162+
})
163+
})
164+
})

solidity/test/ETHStakingTest.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
const {accounts, contract, web3} = require("@openzeppelin/test-environment")
2+
const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot")
3+
4+
const KeepRegistry = contract.fromArtifact("KeepRegistry")
5+
const ETHStaking = contract.fromArtifact("ETHStaking")
6+
7+
const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers")
8+
9+
const BN = web3.utils.BN
10+
11+
const chai = require("chai")
12+
chai.use(require("bn-chai")(BN))
13+
const expect = chai.expect
14+
const assert = chai.assert
15+
16+
describe("ETHStaking", function () {
17+
let registry
18+
let ethStaking
19+
20+
let operator
21+
let authorizer
22+
let beneficiary
23+
let stakeOwner
24+
25+
before(async () => {
26+
operator = accounts[1]
27+
authorizer = accounts[2]
28+
beneficiary = accounts[3]
29+
stakeOwner = accounts[4]
30+
31+
registry = await KeepRegistry.new()
32+
ethStaking = await ETHStaking.new(registry.address)
33+
})
34+
35+
beforeEach(async () => {
36+
await createSnapshot()
37+
})
38+
39+
afterEach(async () => {
40+
await restoreSnapshot()
41+
})
42+
43+
describe("stake", async () => {
44+
it("registers stake", async () => {
45+
await ethStaking.stake(operator, beneficiary, authorizer, {
46+
from: stakeOwner,
47+
})
48+
49+
assert.equal(
50+
await ethStaking.ownerOf(operator),
51+
stakeOwner,
52+
"incorrect stake owner address"
53+
)
54+
55+
assert.equal(
56+
await ethStaking.beneficiaryOf(operator),
57+
beneficiary,
58+
"incorrect beneficiary address"
59+
)
60+
61+
assert.equal(
62+
await ethStaking.authorizerOf(operator),
63+
authorizer,
64+
"incorrect authorizer address"
65+
)
66+
67+
expect(await ethStaking.balanceOf(operator)).to.eq.BN(
68+
0,
69+
"incorrect stake balance"
70+
)
71+
})
72+
73+
it("emits event", async () => {
74+
const receipt = await ethStaking.stake(
75+
operator,
76+
beneficiary,
77+
authorizer,
78+
{
79+
from: stakeOwner,
80+
}
81+
)
82+
83+
await expectEvent(receipt, "Staked", {
84+
owner: stakeOwner,
85+
operator: operator,
86+
beneficiary: beneficiary,
87+
authorizer: authorizer,
88+
})
89+
})
90+
91+
it("registers multiple operators for the same owner", async () => {
92+
const operator2 = accounts[5]
93+
94+
await ethStaking.stake(operator, beneficiary, authorizer, {
95+
from: stakeOwner,
96+
})
97+
98+
await ethStaking.stake(operator2, beneficiary, authorizer, {
99+
from: stakeOwner,
100+
})
101+
102+
assert.deepEqual(
103+
await ethStaking.operatorsOf(stakeOwner),
104+
[operator, operator2],
105+
"incorrect operators for owner"
106+
)
107+
})
108+
109+
it("reverts if operator is already in use", async () => {
110+
await ethStaking.stake(operator, beneficiary, authorizer, {
111+
from: stakeOwner,
112+
})
113+
114+
await expectRevert(
115+
ethStaking.stake(operator, accounts[5], accounts[5]),
116+
"Operator already in use"
117+
)
118+
})
119+
})
120+
})

0 commit comments

Comments
 (0)