Skip to content

Commit

Permalink
payroll: organize some test scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
facuspagnuolo committed Jul 10, 2019
1 parent d4acb4c commit c8dee4d
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 224 deletions.
4 changes: 2 additions & 2 deletions future-apps/payroll/contracts/Payroll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ contract Payroll is EtherTokenConstant, IForwarder, IsContract, AragonApp {
Employee storage employee = employees[employeeId];

// Delete previous token allocations
address[] previousAllowedTokenAddresses = employee.allocationTokenAddresses;
address[] memory previousAllowedTokenAddresses = employee.allocationTokenAddresses;
for (uint256 j = 0; j < previousAllowedTokenAddresses.length; j++) {
delete employee.allocationTokens[previousAllowedTokenAddresses[j]];
}
Expand Down Expand Up @@ -813,7 +813,7 @@ contract Payroll is EtherTokenConstant, IForwarder, IsContract, AragonApp {

function _ensureEmployeeTokenAllocationsIsValid(Employee storage employee_) internal view {
uint256 sum = 0;
address[] storage allocationTokenAddresses = employee_.allocationTokenAddresses;
address[] memory allocationTokenAddresses = employee_.allocationTokenAddresses;
for (uint256 i = 0; i < allocationTokenAddresses.length; i++) {
address token = allocationTokenAddresses[i];
require(allowedTokens[token], ERROR_NOT_ALLOWED_TOKEN);
Expand Down
80 changes: 23 additions & 57 deletions future-apps/payroll/test/contracts/Payroll_employee_info.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,28 @@ contract('Payroll employee info', ([owner, employee]) => {
employeeId = getEventArgument(receipt, 'AddEmployee', 'employeeId').toString()
})

it('adds a new employee', async () => {
const [address, employeeSalary, accruedSalary, bonus, reimbursements, lastPayroll, endDate, allocationTokens] = await payroll.getEmployee(employeeId)

assert.equal(address, employee, 'employee address does not match')
assert.equal(employeeSalary.toString(), salary.toString(), 'employee salary does not match')
assert.equal(accruedSalary.toString(), 0, 'employee accrued salary does not match')
assert.equal(bonus.toString(), 0, 'employee bonus does not match')
assert.equal(reimbursements.toString(), 0, 'employee reimbursements does not match')
assert.equal(lastPayroll.toString(), (await currentTimestamp()).toString(), 'employee last payroll does not match')
assert.equal(endDate.toString(), MAX_UINT64, 'employee end date does not match')
assert.deepEqual(allocationTokens, [], 'employee allocation tokens should be empty')
const itReturnsTheEmployeeInformation = expectedAllocationTokenAddresses => {
it('adds a new employee', async () => {
const [address, employeeSalary, accruedSalary, bonus, reimbursements, lastPayroll, endDate, allocationTokens] = await payroll.getEmployee(employeeId)

assert.equal(address, employee, 'employee address does not match')
assert.equal(employeeSalary.toString(), salary.toString(), 'employee salary does not match')
assert.equal(accruedSalary.toString(), 0, 'employee accrued salary does not match')
assert.equal(bonus.toString(), 0, 'employee bonus does not match')
assert.equal(reimbursements.toString(), 0, 'employee reimbursements does not match')
assert.equal(lastPayroll.toString(), (await currentTimestamp()).toString(), 'employee last payroll does not match')
assert.equal(endDate.toString(), MAX_UINT64, 'employee end date does not match')
assert.deepEqual(allocationTokens, expectedAllocationTokenAddresses, 'employee allocation tokens should be empty')
})
}

context('when the employee has not set an allocation yet', () => {
const expectedAllocationTokenAddresses = []

itReturnsTheEmployeeInformation(expectedAllocationTokenAddresses)
})

context('when the employee sets a allocation', () => {
context('when the employee has already set an allocation', () => {
const tokens = []
const tokenAddresses = []

Expand All @@ -72,11 +80,7 @@ contract('Payroll employee info', ([owner, employee]) => {
await payroll.determineAllocation(tokenAddresses, allocations, { from: employee })
})

it('returns the set allocation tokens', async () => {
const [allocationTokens] = (await payroll.getEmployee(employeeId)).slice(-1)

assert.deepEqual(allocationTokens, tokenAddresses, 'employee allocation tokens should match previous allocation')
})
itReturnsTheEmployeeInformation(tokenAddresses)
})
})

Expand Down Expand Up @@ -114,50 +118,12 @@ contract('Payroll employee info', ([owner, employee]) => {
employeeId = getEventArgument(receipt, 'AddEmployee', 'employeeId')
})

it('adds a new employee', async () => {
it('returns the id of the requested employee', async () => {
const id = await payroll.getEmployeeIdByAddress(address)
const [employeeAddress, employeeSalary, accruedSalary, bonus, reimbursements, lastPayroll, endDate] = await payroll.getEmployee(id)
const [employeeAddress] = await payroll.getEmployee(id)

assert.equal(id.toString(), employeeId.toString(), 'employee id does not match')
assert.equal(employeeAddress, address, 'employee address does not match')
assert.equal(employeeSalary.toString(), salary.toString(), 'employee salary does not match')
assert.equal(accruedSalary.toString(), 0, 'employee accrued salary does not match')
assert.equal(bonus.toString(), 0, 'employee bonus does not match')
assert.equal(reimbursements.toString(), 0, 'employee reimbursements does not match')
assert.equal(lastPayroll.toString(), (await currentTimestamp()).toString(), 'employee last payroll does not match')
assert.equal(endDate.toString(), MAX_UINT64, 'employee end date does not match')
})

context('when the employee sets a allocation', () => {
const tokens = []
const tokenAddresses = []

before('deploy tokens', async () => {
tokens.push(await deployANT(owner, finance))
tokens.push(await deployDAI(owner, finance))

tokens.forEach(token => tokenAddresses.push(token.address))
})

beforeEach('set allowed tokens', async () => {
const from = owner

await payroll.setAllowedToken(tokens[0].address, true, { from })
await payroll.setAllowedToken(tokens[1].address, true, { from })
})

beforeEach('set employee allocation', async () => {
const allocations = tokenAddresses.map(() => 100 / tokenAddresses.length)

await payroll.determineAllocation(tokenAddresses, allocations, { from: employee })
})

it('returns the set allocation tokens', async () => {
const id = await payroll.getEmployeeIdByAddress(address)
const [allocationTokens] = (await payroll.getEmployee(id)).slice(-1)

assert.deepEqual(allocationTokens, tokenAddresses, 'employee allocation tokens should match previous allocation')
})
})
})

Expand Down
37 changes: 30 additions & 7 deletions future-apps/payroll/test/contracts/Payroll_gas_costs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,48 @@ contract('Payroll gas costs', ([owner, employee, anotherEmployee]) => {
})

context('when there is only one allowed token', function () {
it('expends ~338k gas for a single allowed token', async () => {
it('expends ~337k gas for a single allowed token', async () => {
await payroll.determineAllocation([DAI.address], [100], { from: employee })

const { receipt: { cumulativeGasUsed } } = await payroll.payday(PAYMENT_TYPES.PAYROLL, 0, [inverseRate(DAI_RATE)], { from: employee })
const { receipt: { cumulativeGasUsed } } = await payroll.payday(PAYMENT_TYPES.PAYROLL, 0, [], { from: employee })

assert.isAtMost(cumulativeGasUsed, 338000, 'payout gas cost for a single allowed token should be ~338k')
console.log('cumulativeGasUsed:', cumulativeGasUsed)
assert.isAtMost(cumulativeGasUsed, 337000, 'payout gas cost for a single allowed token should be ~338k')
})
})

context('when there are two allowed token', function () {
it('expends ~296k gas per allowed token', async () => {
it('expends ~49k gas in setting a allocation tokens per token', async () => {
const { receipt: { cumulativeGasUsed: oneTokenAllocationGasUsed } } = await payroll.determineAllocation([DAI.address], [100], { from: employee })
const { receipt: { cumulativeGasUsed: twoTokensAllocationGasUsed } } = await payroll.determineAllocation([DAI.address, ANT.address], [60, 40], { from: anotherEmployee })

const gasPerAllocationToken = twoTokensAllocationGasUsed - oneTokenAllocationGasUsed
console.log('gasPerAllocationToken:', gasPerAllocationToken)
assert.isAtMost(gasPerAllocationToken, 49000, 'gas cost increment of setting allocation token sets should be ~49k per token')
})

it('expends ~30k gas in overwriting an allocation set per token', async () => {
await payroll.determineAllocation([DAI.address], [100], { from: employee })
const { receipt: { cumulativeGasUsed: oneTokenAllocationOverwriteGasUsed } } = await payroll.determineAllocation([ANT.address], [100], { from: employee })

await payroll.determineAllocation([DAI.address, ANT.address], [60, 40], { from: anotherEmployee })
const { receipt: { cumulativeGasUsed: twoTokensAllocationOverwriteGasUsed } } = await payroll.determineAllocation([DAI.address, ANT.address], [40, 60], { from: anotherEmployee })

const gasPerAllocationToken = twoTokensAllocationOverwriteGasUsed - oneTokenAllocationOverwriteGasUsed
console.log('gasPerAllocationToken:', gasPerAllocationToken)
assert.isAtMost(gasPerAllocationToken, 30000, 'gas cost increment of overwriting allocation token sets should be ~30k per token')
})

it('expends ~295k gas in payday per allowed token', async () => {
await payroll.determineAllocation([DAI.address], [100], { from: employee })
const { receipt: { cumulativeGasUsed: employeePayoutGasUsed } } = await payroll.payday(PAYMENT_TYPES.PAYROLL, 0, [inverseRate(DAI_RATE)], { from: employee })
const { receipt: { cumulativeGasUsed: employeePayoutGasUsed } } = await payroll.payday(PAYMENT_TYPES.PAYROLL, 0, [], { from: employee })

await payroll.determineAllocation([DAI.address, ANT.address], [60, 40], { from: anotherEmployee })
const { receipt: { cumulativeGasUsed: anotherEmployeePayoutGasUsed } } = await payroll.payday(PAYMENT_TYPES.PAYROLL, 0, [inverseRate(DAI_RATE), inverseRate(ANT_RATE)], { from: anotherEmployee })
const { receipt: { cumulativeGasUsed: anotherEmployeePayoutGasUsed } } = await payroll.payday(PAYMENT_TYPES.PAYROLL, 0, [], { from: anotherEmployee })

const gasPerAllowedToken = anotherEmployeePayoutGasUsed - employeePayoutGasUsed
assert.isAtMost(gasPerAllowedToken, 296000, 'payout gas cost increment per allowed token should be ~296k')
console.log('gasPerAllowedToken:', gasPerAllowedToken)
assert.isAtMost(gasPerAllowedToken, 295000, 'payroll payday gas cost increment per allowed token should be ~295k')
})
})
})
Expand Down
Loading

0 comments on commit c8dee4d

Please sign in to comment.