RefundEscrow.test.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. const { expectThrow } = require('../helpers/expectThrow');
  2. const { EVMRevert } = require('../helpers/EVMRevert');
  3. const expectEvent = require('../helpers/expectEvent');
  4. const { ethGetBalance } = require('../helpers/web3');
  5. const BigNumber = web3.BigNumber;
  6. require('chai')
  7. .use(require('chai-bignumber')(BigNumber))
  8. .should();
  9. const RefundEscrow = artifacts.require('RefundEscrow');
  10. contract('RefundEscrow', function ([_, owner, beneficiary, refundee1, refundee2]) {
  11. const amount = web3.toWei(54.0, 'ether');
  12. const refundees = [refundee1, refundee2];
  13. const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
  14. it('requires a non-null beneficiary', async function () {
  15. await expectThrow(
  16. RefundEscrow.new(ZERO_ADDRESS, { from: owner })
  17. );
  18. });
  19. context('once deployed', function () {
  20. beforeEach(async function () {
  21. this.escrow = await RefundEscrow.new(beneficiary, { from: owner });
  22. });
  23. context('active state', function () {
  24. it('accepts deposits', async function () {
  25. await this.escrow.deposit(refundee1, { from: owner, value: amount });
  26. const deposit = await this.escrow.depositsOf(refundee1);
  27. deposit.should.be.bignumber.equal(amount);
  28. });
  29. it('does not refund refundees', async function () {
  30. await this.escrow.deposit(refundee1, { from: owner, value: amount });
  31. await expectThrow(this.escrow.withdraw(refundee1), EVMRevert);
  32. });
  33. it('does not allow beneficiary withdrawal', async function () {
  34. await this.escrow.deposit(refundee1, { from: owner, value: amount });
  35. await expectThrow(this.escrow.beneficiaryWithdraw(), EVMRevert);
  36. });
  37. });
  38. it('only owner can enter closed state', async function () {
  39. await expectThrow(this.escrow.close({ from: beneficiary }), EVMRevert);
  40. const receipt = await this.escrow.close({ from: owner });
  41. expectEvent.inLogs(receipt.logs, 'Closed');
  42. });
  43. context('closed state', function () {
  44. beforeEach(async function () {
  45. await Promise.all(refundees.map(refundee => this.escrow.deposit(refundee, { from: owner, value: amount })));
  46. await this.escrow.close({ from: owner });
  47. });
  48. it('rejects deposits', async function () {
  49. await expectThrow(this.escrow.deposit(refundee1, { from: owner, value: amount }), EVMRevert);
  50. });
  51. it('does not refund refundees', async function () {
  52. await expectThrow(this.escrow.withdraw(refundee1), EVMRevert);
  53. });
  54. it('allows beneficiary withdrawal', async function () {
  55. const beneficiaryInitialBalance = await ethGetBalance(beneficiary);
  56. await this.escrow.beneficiaryWithdraw();
  57. const beneficiaryFinalBalance = await ethGetBalance(beneficiary);
  58. beneficiaryFinalBalance.sub(beneficiaryInitialBalance).should.be.bignumber.equal(amount * refundees.length);
  59. });
  60. it('prevents entering the refund state', async function () {
  61. await expectThrow(this.escrow.enableRefunds({ from: owner }), EVMRevert);
  62. });
  63. it('prevents re-entering the closed state', async function () {
  64. await expectThrow(this.escrow.close({ from: owner }), EVMRevert);
  65. });
  66. });
  67. it('only owner can enter refund state', async function () {
  68. await expectThrow(this.escrow.enableRefunds({ from: beneficiary }), EVMRevert);
  69. const receipt = await this.escrow.enableRefunds({ from: owner });
  70. expectEvent.inLogs(receipt.logs, 'RefundsEnabled');
  71. });
  72. context('refund state', function () {
  73. beforeEach(async function () {
  74. await Promise.all(refundees.map(refundee => this.escrow.deposit(refundee, { from: owner, value: amount })));
  75. await this.escrow.enableRefunds({ from: owner });
  76. });
  77. it('rejects deposits', async function () {
  78. await expectThrow(this.escrow.deposit(refundee1, { from: owner, value: amount }), EVMRevert);
  79. });
  80. it('refunds refundees', async function () {
  81. for (const refundee of [refundee1, refundee2]) {
  82. const refundeeInitialBalance = await ethGetBalance(refundee);
  83. await this.escrow.withdraw(refundee, { from: owner });
  84. const refundeeFinalBalance = await ethGetBalance(refundee);
  85. refundeeFinalBalance.sub(refundeeInitialBalance).should.be.bignumber.equal(amount);
  86. }
  87. });
  88. it('does not allow beneficiary withdrawal', async function () {
  89. await expectThrow(this.escrow.beneficiaryWithdraw(), EVMRevert);
  90. });
  91. it('prevents entering the closed state', async function () {
  92. await expectThrow(this.escrow.close({ from: owner }), EVMRevert);
  93. });
  94. it('prevents re-entering the refund state', async function () {
  95. await expectThrow(this.escrow.enableRefunds({ from: owner }), EVMRevert);
  96. });
  97. });
  98. });
  99. });