Delete old test helpers.
This commit is contained in:
@ -1,12 +0,0 @@
|
||||
const { ethGetBalance } = require('./web3');
|
||||
|
||||
async function balanceDifference (account, promiseFunc) {
|
||||
const balanceBefore = await ethGetBalance(account);
|
||||
await promiseFunc();
|
||||
const balanceAfter = await ethGetBalance(account);
|
||||
return balanceAfter.minus(balanceBefore);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
balanceDifference,
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
module.exports = {
|
||||
ZERO_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
MAX_UINT256: new BigNumber(2).pow(256).minus(1),
|
||||
MAX_INT256: new BigNumber(2).pow(255).minus(1),
|
||||
MIN_INT256: new BigNumber(2).pow(255).times(-1),
|
||||
};
|
||||
@ -1,7 +0,0 @@
|
||||
function ether (n) {
|
||||
return new web3.BigNumber(web3.toWei(n, 'ether'));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ether,
|
||||
};
|
||||
@ -1,57 +0,0 @@
|
||||
const { should, BigNumber } = require('./setup');
|
||||
|
||||
const SolidityEvent = require('web3/lib/web3/event.js');
|
||||
const { ethGetTransactionReceipt } = require('./web3');
|
||||
|
||||
function inLogs (logs, eventName, eventArgs = {}) {
|
||||
const event = logs.find(function (e) {
|
||||
if (e.event === eventName) {
|
||||
for (const [k, v] of Object.entries(eventArgs)) {
|
||||
contains(e.args, k, v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
should.exist(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
async function inConstruction (contract, eventName, eventArgs = {}) {
|
||||
return inTransaction(contract.transactionHash, contract.constructor, eventName, eventArgs);
|
||||
}
|
||||
|
||||
async function inTransaction (txHash, emitter, eventName, eventArgs = {}) {
|
||||
const receipt = await ethGetTransactionReceipt(txHash);
|
||||
const logs = decodeLogs(receipt.logs, emitter.events);
|
||||
|
||||
return inLogs(logs, eventName, eventArgs);
|
||||
}
|
||||
|
||||
function contains (args, key, value) {
|
||||
if (isBigNumber(args[key])) {
|
||||
args[key].should.be.bignumber.equal(value);
|
||||
} else {
|
||||
args[key].should.be.equal(value);
|
||||
}
|
||||
}
|
||||
|
||||
function isBigNumber (object) {
|
||||
return object.isBigNumber ||
|
||||
object instanceof BigNumber ||
|
||||
(object.constructor && object.constructor.name === 'BigNumber');
|
||||
}
|
||||
|
||||
function decodeLogs (logs, events) {
|
||||
return Array.prototype.concat(...logs.map(log =>
|
||||
log.topics.filter(topic => topic in events).map(topic => {
|
||||
const event = new SolidityEvent(null, events[topic], 0);
|
||||
return event.decode(log);
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
inLogs,
|
||||
inConstruction,
|
||||
inTransaction,
|
||||
};
|
||||
@ -1,25 +0,0 @@
|
||||
const { soliditySha3 } = require('web3-utils');
|
||||
|
||||
const INTERFACE_ID_LENGTH = 4;
|
||||
|
||||
function makeInterfaceId (interfaces = []) {
|
||||
const interfaceIdBuffer = interfaces
|
||||
.map(methodSignature => soliditySha3(methodSignature)) // keccak256
|
||||
.map(h =>
|
||||
Buffer
|
||||
.from(h.substring(2), 'hex')
|
||||
.slice(0, 4) // bytes4()
|
||||
)
|
||||
.reduce((memo, bytes) => {
|
||||
for (let i = 0; i < INTERFACE_ID_LENGTH; i++) {
|
||||
memo[i] = memo[i] ^ bytes[i]; // xor
|
||||
}
|
||||
return memo;
|
||||
}, Buffer.alloc(INTERFACE_ID_LENGTH));
|
||||
|
||||
return `0x${interfaceIdBuffer.toString('hex')}`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
makeInterfaceId,
|
||||
};
|
||||
@ -1,26 +0,0 @@
|
||||
const ethjsABI = require('ethjs-abi');
|
||||
const { ethSendTransaction } = require('./web3');
|
||||
|
||||
function findMethod (abi, name, args) {
|
||||
for (let i = 0; i < abi.length; i++) {
|
||||
const methodArgs = abi[i].inputs.map(input => input.type).join(',');
|
||||
if ((abi[i].name === name) && (methodArgs === args)) {
|
||||
return abi[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function transaction (target, name, argsTypes, argsValues, opts) {
|
||||
const abiMethod = findMethod(target.abi, name, argsTypes);
|
||||
const encodedData = ethjsABI.encodeMethod(abiMethod, argsValues);
|
||||
return target.sendTransaction(Object.assign({ data: encodedData }, opts));
|
||||
}
|
||||
|
||||
function ether (from, to, value) {
|
||||
return ethSendTransaction({ from, to, value, gasPrice: 0 });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ether,
|
||||
transaction,
|
||||
};
|
||||
@ -1,9 +0,0 @@
|
||||
const chai = require('chai');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
const should = chai.use(require('chai-bignumber')(BigNumber)).should();
|
||||
|
||||
module.exports = {
|
||||
BigNumber,
|
||||
should,
|
||||
};
|
||||
@ -1,36 +0,0 @@
|
||||
const { should } = require('./setup');
|
||||
|
||||
async function shouldFailWithMessage (promise, message) {
|
||||
try {
|
||||
await promise;
|
||||
} catch (error) {
|
||||
if (message) {
|
||||
error.message.should.include(message, `Wrong failure type, expected '${message}'`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
should.fail('Expected failure not received');
|
||||
}
|
||||
|
||||
async function reverting (promise) {
|
||||
await shouldFailWithMessage(promise, 'revert');
|
||||
}
|
||||
|
||||
async function throwing (promise) {
|
||||
await shouldFailWithMessage(promise, 'invalid opcode');
|
||||
}
|
||||
|
||||
async function outOfGas (promise) {
|
||||
await shouldFailWithMessage(promise, 'out of gas');
|
||||
}
|
||||
|
||||
async function shouldFail (promise) {
|
||||
await shouldFailWithMessage(promise);
|
||||
}
|
||||
|
||||
shouldFail.reverting = reverting;
|
||||
shouldFail.throwing = throwing;
|
||||
shouldFail.outOfGas = outOfGas;
|
||||
|
||||
module.exports = shouldFail;
|
||||
@ -3,7 +3,6 @@ const PADDED_SIGNATURE_SIZE = 2 * 96; // 96 bytes in hexadecimal string length
|
||||
|
||||
const DUMMY_SIGNATURE = `0x${web3.utils.padLeft('', REAL_SIGNATURE_SIZE)}`;
|
||||
|
||||
// messageHex = '0xdeadbeef'
|
||||
function toEthSignedMessageHash (messageHex) {
|
||||
const messageBuffer = Buffer.from(messageHex.substring(2), 'hex');
|
||||
const prefix = Buffer.from(`\u0019Ethereum Signed Message:\n${messageBuffer.length}`);
|
||||
@ -11,26 +10,13 @@ function toEthSignedMessageHash (messageHex) {
|
||||
}
|
||||
|
||||
// signs message in node (ganache auto-applies "Ethereum Signed Message" prefix)
|
||||
// messageHex = '0xdeadbeef'
|
||||
const signMessage = (signer, messageHex = '0x') => {
|
||||
return web3.eth.sign(messageHex, signer); // actually personal_sign
|
||||
};
|
||||
|
||||
// @TODO - remove this when we migrate to web3-1.0.0
|
||||
const transformToFullName = function (json) {
|
||||
if (json.name.indexOf('(') !== -1) {
|
||||
return json.name;
|
||||
}
|
||||
|
||||
const typeName = json.inputs.map(function (i) { return i.type; }).join();
|
||||
return json.name + '(' + typeName + ')';
|
||||
return web3.eth.sign(messageHex, signer);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a signer between a contract and a signer for a voucher of method, args, and redeemer
|
||||
* Note that `method` is the web3 method, not the truffle-contract method
|
||||
* Well truffle is terrible, but luckily (?) so is web3 < 1.0, so we get to make our own method id
|
||||
* fetcher because the method on the contract isn't actually the SolidityFunction object ಠ_ಠ
|
||||
* @param contract TruffleContract
|
||||
* @param signer address
|
||||
* @param redeemer address
|
||||
@ -47,16 +33,12 @@ const getSignFor = (contract, signer) => (redeemer, methodName, methodArgs = [])
|
||||
if (methodName) {
|
||||
if (methodArgs.length > 0) {
|
||||
parts.push(
|
||||
contract.contract[methodName].getData(...methodArgs.concat([DUMMY_SIGNATURE])).slice(
|
||||
0,
|
||||
-1 * PADDED_SIGNATURE_SIZE
|
||||
)
|
||||
contract.contract.methods[methodName](...methodArgs.concat([DUMMY_SIGNATURE])).encodeABI()
|
||||
.slice(0, -1 * PADDED_SIGNATURE_SIZE)
|
||||
);
|
||||
} else {
|
||||
const abi = contract.abi.find(abi => abi.name === methodName);
|
||||
const name = transformToFullName(abi);
|
||||
const signature = web3.utils.sha3(name).slice(0, 10);
|
||||
parts.push(signature);
|
||||
parts.push(abi.signature);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
const { balanceDifference } = require('../balanceDifference');
|
||||
const send = require('../send');
|
||||
const { ether } = require('../ether');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
contract('balanceDifference', function ([sender, receiver]) {
|
||||
it('returns balance increments', async function () {
|
||||
(await balanceDifference(receiver, () =>
|
||||
send.ether(sender, receiver, ether(1)))
|
||||
).should.be.bignumber.equal(ether(1));
|
||||
});
|
||||
|
||||
it('returns balance decrements', async function () {
|
||||
(await balanceDifference(sender, () =>
|
||||
send.ether(sender, receiver, ether(1)))
|
||||
).should.be.bignumber.equal(ether(-1));
|
||||
});
|
||||
});
|
||||
@ -1,16 +0,0 @@
|
||||
const { ether } = require('../ether');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
describe('ether', function () {
|
||||
it('returns a BigNumber', function () {
|
||||
ether(1, 'ether').should.be.bignumber.equal(new BigNumber(1000000000000000000));
|
||||
});
|
||||
|
||||
it('works with negative amounts', function () {
|
||||
ether(-1, 'ether').should.be.bignumber.equal(new BigNumber(-1000000000000000000));
|
||||
});
|
||||
});
|
||||
@ -1,375 +0,0 @@
|
||||
const expectEvent = require('../expectEvent');
|
||||
const shouldFail = require('../shouldFail');
|
||||
|
||||
const EventEmitter = artifacts.require('EventEmitter');
|
||||
const IndirectEventEmitter = artifacts.require('IndirectEventEmitter');
|
||||
|
||||
const { should, BigNumber } = require('../../helpers/setup');
|
||||
|
||||
describe('expectEvent', function () {
|
||||
beforeEach(async function () {
|
||||
this.constructionValues = {
|
||||
uint: 42,
|
||||
boolean: true,
|
||||
string: 'OpenZeppelin',
|
||||
};
|
||||
|
||||
this.emitter = await EventEmitter.new(
|
||||
this.constructionValues.uint,
|
||||
this.constructionValues.boolean,
|
||||
this.constructionValues.string
|
||||
);
|
||||
});
|
||||
|
||||
describe('inConstructor', function () {
|
||||
context('short uint value', function () {
|
||||
it('accepts emitted events with correct number', async function () {
|
||||
await expectEvent.inConstruction(this.emitter, 'ShortUint',
|
||||
{ value: this.constructionValues.uint }
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', async function () {
|
||||
await shouldFail(expectEvent.inConstruction(this.emitter, 'ShortUint', { value: 23 }));
|
||||
});
|
||||
});
|
||||
|
||||
context('boolean value', function () {
|
||||
it('accepts emitted events with correct value', async function () {
|
||||
await expectEvent.inConstruction(this.emitter, 'Boolean', { value: this.constructionValues.boolean });
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', async function () {
|
||||
await shouldFail(expectEvent.inConstruction(this.emitter, 'Boolean',
|
||||
{ value: !this.constructionValues.boolean }
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
context('string value', function () {
|
||||
it('accepts emitted events with correct string', async function () {
|
||||
await expectEvent.inConstruction(this.emitter, 'String', { value: this.constructionValues.string });
|
||||
});
|
||||
|
||||
it('throws if an incorrect string is passed', async function () {
|
||||
await shouldFail(expectEvent.inConstruction(this.emitter, 'String', { value: 'ClosedZeppelin' }));
|
||||
});
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', async function () {
|
||||
await shouldFail(expectEvent.inConstruction(this.emitter, 'UnemittedEvent'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('inLogs', function () {
|
||||
describe('with no arguments', function () {
|
||||
beforeEach(async function () {
|
||||
({ logs: this.logs } = await this.emitter.emitArgumentless());
|
||||
});
|
||||
|
||||
it('accepts emitted events', function () {
|
||||
expectEvent.inLogs(this.logs, 'Argumentless');
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('with single argument', function () {
|
||||
context('short uint value', function () {
|
||||
beforeEach(async function () {
|
||||
this.value = 42;
|
||||
({ logs: this.logs } = await this.emitter.emitShortUint(this.value));
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct JavaScript number', function () {
|
||||
expectEvent.inLogs(this.logs, 'ShortUint', { value: this.value });
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct BigNumber', function () {
|
||||
expectEvent.inLogs(this.logs, 'ShortUint', { value: new BigNumber(this.value) });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value }));
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'ShortUint', { value: 23 }));
|
||||
});
|
||||
});
|
||||
|
||||
context('short int value', function () {
|
||||
beforeEach(async function () {
|
||||
this.value = -42;
|
||||
({ logs: this.logs } = await this.emitter.emitShortInt(this.value));
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct JavaScript number', function () {
|
||||
expectEvent.inLogs(this.logs, 'ShortInt', { value: this.value });
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct BigNumber', function () {
|
||||
expectEvent.inLogs(this.logs, 'ShortInt', { value: new BigNumber(this.value) });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value }));
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'ShortInt', { value: -23 }));
|
||||
});
|
||||
});
|
||||
|
||||
context('long uint value', function () {
|
||||
beforeEach(async function () {
|
||||
this.bigNumValue = new BigNumber('123456789012345678901234567890');
|
||||
({ logs: this.logs } = await this.emitter.emitLongUint(this.bigNumValue));
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct BigNumber', function () {
|
||||
expectEvent.inLogs(this.logs, 'LongUint', { value: this.bigNumValue });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.bigNumValue }));
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'LongUint', { value: 2300 }));
|
||||
});
|
||||
});
|
||||
|
||||
context('long int value', function () {
|
||||
beforeEach(async function () {
|
||||
this.bigNumValue = new BigNumber('-123456789012345678901234567890');
|
||||
({ logs: this.logs } = await this.emitter.emitLongInt(this.bigNumValue));
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct BigNumber', function () {
|
||||
expectEvent.inLogs(this.logs, 'LongInt', { value: this.bigNumValue });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.bigNumValue }));
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'LongInt', { value: -2300 }));
|
||||
});
|
||||
});
|
||||
|
||||
context('address value', function () {
|
||||
beforeEach(async function () {
|
||||
this.value = '0x811412068e9fbf25dc300a29e5e316f7122b282c';
|
||||
({ logs: this.logs } = await this.emitter.emitAddress(this.value));
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct address', function () {
|
||||
expectEvent.inLogs(this.logs, 'Address', { value: this.value });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value }));
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', function () {
|
||||
should.Throw(() =>
|
||||
expectEvent.inLogs(this.logs, 'Address', { value: '0x21d04e022e0b52b5d5bcf90b7f1aabf406be002d' })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('boolean value', function () {
|
||||
beforeEach(async function () {
|
||||
this.value = true;
|
||||
({ logs: this.logs } = await this.emitter.emitBoolean(this.value));
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct address', function () {
|
||||
expectEvent.inLogs(this.logs, 'Boolean', { value: this.value });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value }));
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'Boolean', { value: false }));
|
||||
});
|
||||
});
|
||||
|
||||
context('string value', function () {
|
||||
beforeEach(async function () {
|
||||
this.value = 'OpenZeppelin';
|
||||
({ logs: this.logs } = await this.emitter.emitString(this.value));
|
||||
});
|
||||
|
||||
it('accepts emitted events with correct string', function () {
|
||||
expectEvent.inLogs(this.logs, 'String', { value: this.value });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.value }));
|
||||
});
|
||||
|
||||
it('throws if an incorrect value is passed', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'String', { value: 'ClosedZeppelin' }));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with multiple arguments', function () {
|
||||
beforeEach(async function () {
|
||||
this.uintValue = new BigNumber('123456789012345678901234567890');
|
||||
this.booleanValue = true;
|
||||
this.stringValue = 'OpenZeppelin';
|
||||
({ logs: this.logs } =
|
||||
await this.emitter.emitLongUintBooleanString(this.uintValue, this.booleanValue, this.stringValue));
|
||||
});
|
||||
|
||||
it('accepts correct values', function () {
|
||||
expectEvent.inLogs(this.logs, 'LongUintBooleanString', {
|
||||
uintValue: this.uintValue, booleanValue: this.booleanValue, stringValue: this.stringValue,
|
||||
});
|
||||
});
|
||||
|
||||
it('throws with correct values assigned to wrong arguments', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', {
|
||||
uintValue: this.booleanValue, booleanValue: this.uintValue, stringValue: this.stringValue,
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws when any of the values is incorrect', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', {
|
||||
uintValue: 23, booleanValue: this.booleanValue, stringValue: this.stringValue,
|
||||
}));
|
||||
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', {
|
||||
uintValue: this.uintValue, booleanValue: false, stringValue: this.stringValue,
|
||||
}));
|
||||
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'LongUintBooleanString', {
|
||||
uintValue: this.uintValue, booleanValue: this.booleanValue, stringValue: 'ClosedZeppelin',
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('with multiple events', function () {
|
||||
beforeEach(async function () {
|
||||
this.uintValue = 42;
|
||||
this.booleanValue = true;
|
||||
({ logs: this.logs } = await this.emitter.emitLongUintAndBoolean(this.uintValue, this.booleanValue));
|
||||
});
|
||||
|
||||
it('accepts all emitted events with correct values', function () {
|
||||
expectEvent.inLogs(this.logs, 'LongUint', { value: this.uintValue });
|
||||
expectEvent.inLogs(this.logs, 'Boolean', { value: this.booleanValue });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'UnemittedEvent', { value: this.uintValue }));
|
||||
});
|
||||
|
||||
it('throws if incorrect values are passed', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'LongUint', { value: 23 }));
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'Boolean', { value: false }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('with events emitted by an indirectly called contract', function () {
|
||||
beforeEach(async function () {
|
||||
this.secondEmitter = await IndirectEventEmitter.new();
|
||||
|
||||
this.value = 'OpenZeppelin';
|
||||
({ logs: this.logs } = await this.emitter.emitStringAndEmitIndirectly(this.value, this.secondEmitter.address));
|
||||
});
|
||||
|
||||
it('accepts events emitted by the directly called contract', function () {
|
||||
expectEvent.inLogs(this.logs, 'String', { value: this.value });
|
||||
});
|
||||
|
||||
it('throws when passing events emitted by the indirectly called contract', function () {
|
||||
should.Throw(() => expectEvent.inLogs(this.logs, 'IndirectString', { value: this.value }));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('inTransaction', function () {
|
||||
describe('when emitting from called contract and indirect calls', function () {
|
||||
context('string value', function () {
|
||||
beforeEach(async function () {
|
||||
this.secondEmitter = await IndirectEventEmitter.new();
|
||||
|
||||
this.value = 'OpenZeppelin';
|
||||
const receipt = await this.emitter.emitStringAndEmitIndirectly(this.value, this.secondEmitter.address);
|
||||
this.txHash = receipt.tx;
|
||||
});
|
||||
|
||||
context('with directly called contract', function () {
|
||||
it('accepts emitted events with correct string', async function () {
|
||||
await expectEvent.inTransaction(this.txHash, EventEmitter, 'String', { value: this.value });
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'UnemittedEvent',
|
||||
{ value: this.value }
|
||||
));
|
||||
});
|
||||
|
||||
it('throws if an incorrect string is passed', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'String',
|
||||
{ value: 'ClosedZeppelin' }
|
||||
));
|
||||
});
|
||||
|
||||
it('throws if an event emitted from other contract is passed', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString',
|
||||
{ value: this.value }
|
||||
));
|
||||
});
|
||||
|
||||
it('throws if an incorrect emitter is passed', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String',
|
||||
{ value: this.value }
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
context('with indirectly called contract', function () {
|
||||
it('accepts events emitted from other contracts', async function () {
|
||||
await expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'IndirectString',
|
||||
{ value: this.value }
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if an unemitted event is requested', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'UnemittedEvent',
|
||||
{ value: this.value }
|
||||
));
|
||||
});
|
||||
|
||||
it('throws if an incorrect string is passed', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'IndirectString',
|
||||
{ value: 'ClosedZeppelin' }
|
||||
));
|
||||
});
|
||||
|
||||
it('throws if an event emitted from other contract is passed', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, IndirectEventEmitter, 'String',
|
||||
{ value: this.value }
|
||||
));
|
||||
});
|
||||
|
||||
it('throws if an incorrect emitter is passed', async function () {
|
||||
await shouldFail(expectEvent.inTransaction(this.txHash, EventEmitter, 'IndirectString',
|
||||
{ value: this.value }
|
||||
));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,20 +0,0 @@
|
||||
const { makeInterfaceId } = require('../makeInterfaceId');
|
||||
|
||||
const OwnableInterfaceId = artifacts.require('OwnableInterfaceId');
|
||||
|
||||
require('chai')
|
||||
.should();
|
||||
|
||||
describe('makeInterfaceId', function () {
|
||||
it('calculates the EIP165 interface id from function signatures', async function () {
|
||||
const calculator = await OwnableInterfaceId.new();
|
||||
const ownableId = await calculator.getInterfaceId();
|
||||
|
||||
makeInterfaceId([
|
||||
'owner()',
|
||||
'isOwner()',
|
||||
'renounceOwnership()',
|
||||
'transferOwnership(address)',
|
||||
]).should.equal(ownableId);
|
||||
});
|
||||
});
|
||||
@ -1,70 +0,0 @@
|
||||
const send = require('../send');
|
||||
const shouldFail = require('../shouldFail');
|
||||
const expectEvent = require('../expectEvent');
|
||||
const { ether } = require('../ether');
|
||||
const { ethGetBalance } = require('../web3');
|
||||
|
||||
const Acknowledger = artifacts.require('Acknowledger');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
contract('send', function ([sender, receiver]) {
|
||||
describe('ether', function () {
|
||||
it('sends ether with no gas cost', async function () {
|
||||
const value = ether(1);
|
||||
|
||||
const initialSenderBalance = await ethGetBalance(sender);
|
||||
const initialReceiverBalance = await ethGetBalance(receiver);
|
||||
|
||||
await send.ether(sender, receiver, value);
|
||||
|
||||
const finalSenderBalance = await ethGetBalance(sender);
|
||||
const finalReceiverBalance = await ethGetBalance(receiver);
|
||||
|
||||
finalSenderBalance.sub(initialSenderBalance).should.be.bignumber.equal(-value);
|
||||
finalReceiverBalance.sub(initialReceiverBalance).should.be.bignumber.equal(value);
|
||||
});
|
||||
|
||||
it('throws if the sender balance is insufficient', async function () {
|
||||
const value = (await ethGetBalance(sender)).plus(1);
|
||||
|
||||
await shouldFail(send.ether(sender, receiver, value));
|
||||
});
|
||||
});
|
||||
|
||||
describe('transaction', function () {
|
||||
beforeEach(async function () {
|
||||
this.acknowledger = await Acknowledger.new();
|
||||
});
|
||||
|
||||
it('calls a function from its signature ', async function () {
|
||||
const { logs } = await send.transaction(this.acknowledger, 'foo', 'uint256', [3]);
|
||||
expectEvent.inLogs(logs, 'AcknowledgeFoo', { a: 3 });
|
||||
});
|
||||
|
||||
it('calls overloaded functions with less arguments', async function () {
|
||||
const { logs } = await send.transaction(this.acknowledger, 'bar', 'uint256', [3]);
|
||||
expectEvent.inLogs(logs, 'AcknowledgeBarSingle', { a: 3 });
|
||||
});
|
||||
|
||||
it('calls overloaded functions with more arguments', async function () {
|
||||
const { logs } = await send.transaction(this.acknowledger, 'bar', 'uint256,uint256', [3, 5]);
|
||||
expectEvent.inLogs(logs, 'AcknowledgeBarDouble', { a: 3, b: 5 });
|
||||
});
|
||||
|
||||
it('throws if the number of arguments does not match', async function () {
|
||||
await shouldFail(send.transaction(this.acknowledger, 'foo', 'uint256, uint256', [3, 5]));
|
||||
});
|
||||
|
||||
it('throws if the method does not exist', async function () {
|
||||
await shouldFail(send.transaction(this.acknowledger, 'baz', 'uint256', [3]));
|
||||
});
|
||||
|
||||
it('throws if there is a mismatch in the number of types and values', async function () {
|
||||
await shouldFail(send.transaction(this.acknowledger, 'foo', 'uint256', [3, 3]));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,95 +0,0 @@
|
||||
const shouldFail = require('../shouldFail');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
const should = require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
const Failer = artifacts.require('Failer');
|
||||
|
||||
async function assertFailure (promise) {
|
||||
try {
|
||||
await promise;
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
should.fail();
|
||||
}
|
||||
|
||||
describe('shouldFail', function () {
|
||||
beforeEach(async function () {
|
||||
this.failer = await Failer.new();
|
||||
});
|
||||
|
||||
describe('shouldFail', function () {
|
||||
it('rejects if no failure occurs', async function () {
|
||||
await assertFailure(shouldFail(this.failer.dontFail()));
|
||||
});
|
||||
|
||||
it('accepts a revert', async function () {
|
||||
await shouldFail(this.failer.failWithRevert());
|
||||
});
|
||||
|
||||
it('accepts a throw', async function () {
|
||||
await shouldFail(this.failer.failWithThrow());
|
||||
});
|
||||
|
||||
it('accepts an out of gas', async function () {
|
||||
await shouldFail(this.failer.failWithOutOfGas({ gas: 2000000 }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('reverting', function () {
|
||||
it('rejects if no failure occurs', async function () {
|
||||
await assertFailure(shouldFail.reverting(this.failer.dontFail()));
|
||||
});
|
||||
|
||||
it('accepts a revert', async function () {
|
||||
await shouldFail.reverting(this.failer.failWithRevert());
|
||||
});
|
||||
|
||||
it('rejects a throw', async function () {
|
||||
await assertFailure(shouldFail.reverting(this.failer.failWithThrow()));
|
||||
});
|
||||
|
||||
it('rejects an outOfGas', async function () {
|
||||
await assertFailure(shouldFail.reverting(this.failer.failWithOutOfGas({ gas: 2000000 })));
|
||||
});
|
||||
});
|
||||
|
||||
describe('throwing', function () {
|
||||
it('rejects if no failure occurs', async function () {
|
||||
await assertFailure(shouldFail.throwing(this.failer.dontFail()));
|
||||
});
|
||||
|
||||
it('accepts a throw', async function () {
|
||||
await shouldFail.throwing(this.failer.failWithThrow());
|
||||
});
|
||||
|
||||
it('rejects a throw', async function () {
|
||||
await assertFailure(shouldFail.throwing(this.failer.failWithRevert()));
|
||||
});
|
||||
|
||||
it('rejects an outOfGas', async function () {
|
||||
await assertFailure(shouldFail.throwing(this.failer.failWithOutOfGas({ gas: 2000000 })));
|
||||
});
|
||||
});
|
||||
|
||||
describe('outOfGas', function () {
|
||||
it('rejects if no failure occurs', async function () {
|
||||
await assertFailure(shouldFail.outOfGas(this.failer.dontFail()));
|
||||
});
|
||||
|
||||
it('accepts an out of gas', async function () {
|
||||
await shouldFail.outOfGas(this.failer.failWithOutOfGas({ gas: 2000000 }));
|
||||
});
|
||||
|
||||
it('rejects a revert', async function () {
|
||||
await assertFailure(shouldFail.outOfGas(this.failer.failWithRevert()));
|
||||
});
|
||||
|
||||
it('rejects a throw', async function () {
|
||||
await assertFailure(shouldFail.outOfGas(this.failer.failWithThrow()));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,77 +0,0 @@
|
||||
const time = require('../time');
|
||||
const shouldFail = require('../shouldFail');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
describe('time', function () {
|
||||
const TOLERANCE_SECONDS = 1;
|
||||
|
||||
describe('duration', function () {
|
||||
it('converts seconds to seconds', function () {
|
||||
time.duration.seconds(1).should.equal(1);
|
||||
});
|
||||
|
||||
it('converts minutes to seconds', function () {
|
||||
time.duration.minutes(1).should.equal(60);
|
||||
});
|
||||
|
||||
it('converts hours to seconds', function () {
|
||||
time.duration.hours(1).should.equal(60 * 60);
|
||||
});
|
||||
|
||||
it('converts days to seconds', function () {
|
||||
time.duration.days(1).should.equal(60 * 60 * 24);
|
||||
});
|
||||
|
||||
it('converts weeks to seconds', function () {
|
||||
time.duration.weeks(1).should.equal(60 * 60 * 24 * 7);
|
||||
});
|
||||
|
||||
it('converts years to seconds', function () {
|
||||
time.duration.years(1).should.equal(60 * 60 * 24 * 365);
|
||||
});
|
||||
});
|
||||
|
||||
describe('advanceBlock', function () {
|
||||
it('increases the block number by one', async function () {
|
||||
const startingBlock = web3.eth.blockNumber;
|
||||
await time.advanceBlock();
|
||||
web3.eth.blockNumber.should.be.bignumber.equal(startingBlock + 1);
|
||||
});
|
||||
});
|
||||
|
||||
context('with starting time', function () {
|
||||
beforeEach(async function () {
|
||||
await time.advanceBlock();
|
||||
this.start = await time.latest();
|
||||
});
|
||||
|
||||
describe('increase', function () {
|
||||
it('increases time by a duration', async function () {
|
||||
await time.increase(time.duration.hours(1));
|
||||
|
||||
const end = this.start + time.duration.hours(1);
|
||||
(await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS);
|
||||
});
|
||||
|
||||
it('throws with negative durations', async function () {
|
||||
await shouldFail(time.increase(-1));
|
||||
});
|
||||
});
|
||||
|
||||
describe('increaseTo', function () {
|
||||
it('increases time to a time in the future', async function () {
|
||||
const end = this.start + time.duration.hours(1);
|
||||
await time.increaseTo(end);
|
||||
(await time.latest()).should.be.closeTo(end, TOLERANCE_SECONDS);
|
||||
});
|
||||
|
||||
it('throws with a time in the past', async function () {
|
||||
await shouldFail(time.increaseTo(this.start - 30));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,60 +0,0 @@
|
||||
const { ethGetBlock } = require('./web3');
|
||||
const pify = require('pify');
|
||||
|
||||
function advanceBlock () {
|
||||
return pify(web3.currentProvider.sendAsync)({
|
||||
jsonrpc: '2.0',
|
||||
method: 'evm_mine',
|
||||
});
|
||||
}
|
||||
|
||||
// Returns the time of the last mined block in seconds
|
||||
async function latest () {
|
||||
const block = await ethGetBlock('latest');
|
||||
return block.timestamp;
|
||||
}
|
||||
|
||||
// Increases ganache time by the passed duration in seconds
|
||||
async function increase (duration) {
|
||||
if (duration < 0) throw Error(`Cannot increase time by a negative amount (${duration})`);
|
||||
|
||||
await pify(web3.currentProvider.sendAsync)({
|
||||
jsonrpc: '2.0',
|
||||
method: 'evm_increaseTime',
|
||||
params: [duration],
|
||||
});
|
||||
|
||||
await advanceBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Beware that due to the need of calling two separate ganache methods and rpc calls overhead
|
||||
* it's hard to increase time precisely to a target point so design your test to tolerate
|
||||
* small fluctuations from time to time.
|
||||
*
|
||||
* @param target time in seconds
|
||||
*/
|
||||
async function increaseTo (target) {
|
||||
const now = (await latest());
|
||||
|
||||
if (target < now) throw Error(`Cannot increase current time (${now}) to a moment in the past (${target})`);
|
||||
const diff = target - now;
|
||||
return increase(diff);
|
||||
}
|
||||
|
||||
const duration = {
|
||||
seconds: function (val) { return val; },
|
||||
minutes: function (val) { return val * this.seconds(60); },
|
||||
hours: function (val) { return val * this.minutes(60); },
|
||||
days: function (val) { return val * this.hours(24); },
|
||||
weeks: function (val) { return val * this.days(7); },
|
||||
years: function (val) { return val * this.days(365); },
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
advanceBlock,
|
||||
latest,
|
||||
increase,
|
||||
increaseTo,
|
||||
duration,
|
||||
};
|
||||
@ -1,10 +0,0 @@
|
||||
const pify = require('pify');
|
||||
|
||||
const ethAsync = pify(web3.eth);
|
||||
|
||||
module.exports = {
|
||||
ethGetBalance: ethAsync.getBalance,
|
||||
ethGetBlock: ethAsync.getBlock,
|
||||
ethGetTransactionReceipt: ethAsync.getTransactionReceipt,
|
||||
ethSendTransaction: ethAsync.sendTransaction,
|
||||
};
|
||||
Reference in New Issue
Block a user