2017-10-19 04:28:45 +03:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var assert = require('assert');
|
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
if (global.ethers) {
|
|
|
|
console.log('Using global ethers; ' + __filename);
|
|
|
|
var ethers = global.ethers;
|
|
|
|
} else {
|
|
|
|
var ethers = require('..');
|
2017-10-19 04:28:45 +03:00
|
|
|
}
|
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
var utils = require('./utils');
|
2017-10-19 04:28:45 +03:00
|
|
|
|
2017-11-22 03:24:44 +03:00
|
|
|
function equals(actual, expected) {
|
|
|
|
|
2017-10-19 04:28:45 +03:00
|
|
|
// Array (treat recursively)
|
2017-11-22 03:24:44 +03:00
|
|
|
if (Array.isArray(actual)) {
|
|
|
|
if (!Array.isArray(expected) || actual.length !== expected.length) { return false; }
|
|
|
|
for (var i = 0; i < actual.length; i++) {
|
|
|
|
if (!equals(actual[i], expected[i])) { return false; }
|
2017-10-19 04:28:45 +03:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-22 03:24:44 +03:00
|
|
|
if (typeof(actual) === 'number') { actual = utils.bigNumberify(actual); }
|
|
|
|
if (typeof(expected) === 'number') { expected = utils.bigNumberify(expected); }
|
|
|
|
|
2017-10-19 04:28:45 +03:00
|
|
|
// BigNumber
|
2017-11-22 03:24:44 +03:00
|
|
|
if (actual.eq) {
|
|
|
|
if (typeof(expected) === 'string' && expected.match(/^-?0x[0-9A-Fa-f]*$/)) {
|
|
|
|
var neg = (expected.substring(0, 1) === '-');
|
|
|
|
if (neg) { expected = expected.substring(1); }
|
|
|
|
expected = utils.bigNumberify(expected);
|
|
|
|
if (neg) { expected = expected.mul(-1); }
|
|
|
|
}
|
|
|
|
if (!actual.eq(expected)) { return false; }
|
2017-10-19 04:28:45 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Uint8Array
|
2017-11-22 03:24:44 +03:00
|
|
|
if (expected.buffer) {
|
|
|
|
if (!utils.isHexString(actual)) { return false; }
|
|
|
|
actual = utils.arrayify(actual);
|
2017-10-19 04:28:45 +03:00
|
|
|
|
2017-11-22 03:24:44 +03:00
|
|
|
if (!actual.buffer || actual.length !== expected.length) { return false; }
|
|
|
|
for (var i = 0; i < actual.length; i++) {
|
|
|
|
if (actual[i] !== expected[i]) { return false; }
|
2017-10-19 04:28:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
// Maybe address?
|
|
|
|
try {
|
|
|
|
var actualAddress = ethers.utils.getAddress(actual);
|
|
|
|
var expectedAddress = ethers.utils.getAddress(expected);
|
|
|
|
return (actualAddress === expectedAddress);
|
|
|
|
} catch (error) { }
|
2017-10-19 04:28:45 +03:00
|
|
|
|
|
|
|
// Something else
|
2017-11-22 03:24:44 +03:00
|
|
|
return (actual === expected);
|
2017-10-19 04:28:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-11 03:20:18 +03:00
|
|
|
function getValues(object, format, named) {
|
2017-10-19 04:28:45 +03:00
|
|
|
if (Array.isArray(object)) {
|
|
|
|
var result = [];
|
|
|
|
object.forEach(function(object) {
|
2018-01-11 03:20:18 +03:00
|
|
|
result.push(getValues(object, format, named));
|
2017-10-19 04:28:45 +03:00
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (object.type) {
|
|
|
|
case 'number':
|
|
|
|
return utils.bigNumberify(object.value);
|
|
|
|
|
|
|
|
case 'boolean':
|
|
|
|
case 'string':
|
|
|
|
return object.value;
|
|
|
|
|
|
|
|
case 'buffer':
|
|
|
|
return utils.arrayify(object.value);
|
|
|
|
|
2017-11-07 03:35:18 +03:00
|
|
|
case 'tuple':
|
2018-01-11 03:20:18 +03:00
|
|
|
var result = getValues(object.value, format, named);
|
|
|
|
if (named) {
|
|
|
|
var namedResult = {};
|
|
|
|
result.forEach(function(value, index) {
|
|
|
|
namedResult['r' + String(index)] = value;
|
|
|
|
});
|
|
|
|
return namedResult;
|
|
|
|
}
|
|
|
|
return result;
|
2017-11-07 03:35:18 +03:00
|
|
|
|
2017-10-19 04:28:45 +03:00
|
|
|
default:
|
|
|
|
throw new Error('invalid type - ' + object.type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
describe('ABI Coder Encoding', function() {
|
|
|
|
var coder = ethers.utils.AbiCoder.defaultCoder;
|
2017-10-19 04:28:45 +03:00
|
|
|
|
|
|
|
var tests = utils.loadTests('contract-interface');
|
|
|
|
tests.forEach(function(test) {
|
|
|
|
var values = getValues(JSON.parse(test.normalizedValues));
|
|
|
|
var types = JSON.parse(test.types);
|
|
|
|
var result = test.result;
|
|
|
|
|
|
|
|
var title = test.name + ' => (' + test.types + ') = (' + test.normalizedValues + ')';
|
|
|
|
|
|
|
|
it(('encodes paramters - ' + test.name + ' - ' + test.types), function() {
|
2018-03-05 03:31:09 +03:00
|
|
|
var encoded = coder.encode(types, values);
|
2017-10-19 04:28:45 +03:00
|
|
|
assert.equal(encoded, result, 'encoded data - ' + title);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
describe('ABI Coder Decoding', function() {
|
|
|
|
var coder = ethers.utils.AbiCoder.defaultCoder;
|
2017-10-19 04:28:45 +03:00
|
|
|
|
|
|
|
var tests = utils.loadTests('contract-interface');
|
|
|
|
tests.forEach(function(test) {
|
|
|
|
var values = getValues(JSON.parse(test.normalizedValues));
|
|
|
|
var types = JSON.parse(test.types);
|
|
|
|
var result = test.result;
|
|
|
|
|
|
|
|
var title = test.name + ' => (' + test.types + ') = (' + test.normalizedValues + ')';
|
|
|
|
|
|
|
|
it(('decodes parameters - ' + test.name + ' - ' + test.types), function() {
|
2018-03-05 03:31:09 +03:00
|
|
|
var decoded = coder.decode(types, result);
|
2017-10-19 09:55:38 +03:00
|
|
|
|
2017-11-22 03:24:44 +03:00
|
|
|
assert.ok(equals(decoded, values), 'decoded parameters - ' + title);
|
2017-11-07 03:35:18 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
describe('ABI Coder ABIv2 Encoding', function() {
|
|
|
|
var coder = ethers.utils.AbiCoder.defaultCoder;
|
2017-11-07 03:35:18 +03:00
|
|
|
|
|
|
|
var tests = utils.loadTests('contract-interface-abi2');
|
|
|
|
tests.forEach(function(test) {
|
|
|
|
var values = getValues(JSON.parse(test.values));
|
2018-01-11 03:20:18 +03:00
|
|
|
var namedValues = getValues(JSON.parse(test.values), undefined, true);
|
2017-11-07 03:35:18 +03:00
|
|
|
var types = JSON.parse(test.types);
|
|
|
|
var expected = test.result;
|
|
|
|
var title = test.name + ' => (' + test.types + ') = (' + test.value + ')';
|
|
|
|
|
2018-01-11 03:20:18 +03:00
|
|
|
it(('encodes ABIv2 parameters - ' + test.name + ' - ' + test.types), function() {
|
2018-03-05 03:31:09 +03:00
|
|
|
var encoded = coder.encode(types, values);
|
2018-01-11 03:20:18 +03:00
|
|
|
assert.equal(encoded, expected, 'encoded positional parameters - ' + title);
|
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
var outputNames = [];
|
|
|
|
JSON.parse(test.interface)[0].outputs.forEach(function(output) {
|
|
|
|
outputNames.push(output.name);
|
|
|
|
});
|
|
|
|
var namedEncoded = coder.encode(outputNames, types, values);
|
2018-01-11 03:20:18 +03:00
|
|
|
assert.equal(namedEncoded, expected, 'encoded named parameters - ' + title);
|
2017-11-22 03:24:44 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-11-07 03:35:18 +03:00
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
describe('ABI Coder ABIv2 Decoding', function() {
|
|
|
|
var coder = ethers.utils.AbiCoder.defaultCoder;
|
2017-11-07 03:35:18 +03:00
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
var tests = utils.loadTests('contract-interface-abi2');
|
|
|
|
tests.forEach(function(test) {
|
|
|
|
var values = getValues(JSON.parse(test.values));
|
|
|
|
var types = JSON.parse(test.types);
|
|
|
|
var result = test.result;
|
|
|
|
var title = test.name + ' => (' + test.types + ') = (' + test.values + ')';
|
2017-11-22 03:24:44 +03:00
|
|
|
|
2018-03-05 03:31:09 +03:00
|
|
|
it(('decodes ABIv2 parameters - ' + test.name + ' - ' + test.types), function() {
|
|
|
|
var decoded = coder.decode(types, result);
|
|
|
|
assert.ok(equals(decoded, values), 'decoded positional parameters - ' + title);
|
2018-06-16 00:50:22 +03:00
|
|
|
|
|
|
|
// Test for mutation
|
|
|
|
// https://github.com/ethers-io/ethers.js/issues/200
|
|
|
|
// https://github.com/ethers-io/ethers.js/issues/201
|
|
|
|
|
|
|
|
// @TODO: Expose parseParameter
|
|
|
|
// Check that it works with objects as well as strings
|
|
|
|
var expandedTypes = [];
|
|
|
|
types.forEach(function(type) {
|
|
|
|
var sig = 'function foo(' + type + ' foo)';
|
|
|
|
var abi = ethers.utils.AbiCoder.parseSignature(sig);
|
|
|
|
expandedTypes.push(abi.inputs[0]);
|
|
|
|
});
|
|
|
|
|
|
|
|
var typesBefore = JSON.stringify(expandedTypes);
|
|
|
|
|
|
|
|
decoded = coder.decode(expandedTypes, result);
|
|
|
|
assert.ok(equals(decoded, values), 'decoded positional parameters - ' + title);
|
|
|
|
|
|
|
|
assert.equal(typesBefore, JSON.stringify(expandedTypes), 'decoding does not modify the types');
|
2018-03-05 03:31:09 +03:00
|
|
|
});
|
2017-11-22 03:24:44 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Test Contract Events', function() {
|
|
|
|
|
|
|
|
var tests = utils.loadTests('contract-events');
|
|
|
|
tests.forEach(function(test, index) {
|
|
|
|
it(('decodes event parameters - ' + test.name + ' - ' + test.types), function() {
|
2018-03-05 03:31:09 +03:00
|
|
|
var contract = new ethers.Interface(test.interface);
|
|
|
|
var event = contract.events.testEvent;
|
2017-11-22 03:24:44 +03:00
|
|
|
var parsed = event.parse(test.topics, test.data);
|
|
|
|
|
|
|
|
test.normalizedValues.forEach(function(expected, index) {
|
|
|
|
if (test.hashed[index]) {
|
|
|
|
assert.ok(equals(parsed[index].hash, expected), 'parsed event indexed parameter matches - ' + index);
|
|
|
|
} else {
|
|
|
|
assert.ok(equals(parsed[index], expected), 'parsed event parameter matches - ' + index);
|
|
|
|
}
|
|
|
|
});
|
2017-11-07 03:35:18 +03:00
|
|
|
});
|
|
|
|
});
|
2017-11-22 03:24:44 +03:00
|
|
|
|
|
|
|
tests.forEach(function(test, index) {
|
|
|
|
it(('decodes event data - ' + test.name + ' - ' + test.types), function() {
|
2018-03-05 03:31:09 +03:00
|
|
|
var contract = new ethers.Interface(test.interface);
|
|
|
|
var event = contract.events.testEvent;
|
2017-11-22 03:24:44 +03:00
|
|
|
var parsed = event.parse(test.data);
|
|
|
|
|
|
|
|
test.normalizedValues.forEach(function(expected, index) {
|
|
|
|
if (test.indexed[index]) {
|
|
|
|
assert.ok((parsed[index].indexed && parsed[index].hash == null), 'parsed event data has empty Indexed - ' + index);
|
|
|
|
} else {
|
|
|
|
assert.ok(equals(parsed[index], expected), 'parsed event data matches - ' + index);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-11-07 03:35:18 +03:00
|
|
|
});
|
2018-01-10 04:45:38 +03:00
|
|
|
|
|
|
|
describe('Test Interface Signatures', function() {
|
2018-03-05 03:31:09 +03:00
|
|
|
var Interface = ethers.Interface;
|
2018-01-10 04:45:38 +03:00
|
|
|
|
|
|
|
var tests = utils.loadTests('contract-signatures');
|
|
|
|
tests.forEach(function(test) {
|
|
|
|
var contract = new Interface(test.abi);
|
|
|
|
it('derives the correct signature - ' + test.name, function() {
|
|
|
|
assert.equal(contract.functions.testSig.signature, test.signature,
|
|
|
|
'derived the correct signature');
|
|
|
|
assert.equal(contract.functions.testSig.sighash, test.sigHash,
|
|
|
|
'derived the correct signature hash');
|
|
|
|
})
|
|
|
|
});
|
|
|
|
});
|
2018-03-18 00:39:45 +03:00
|
|
|
|
|
|
|
describe('Test Invalid Input', function() {
|
|
|
|
var coder = ethers.utils.AbiCoder.defaultCoder;
|
|
|
|
it('null input failed', function() {
|
|
|
|
assert.throws(function() {
|
|
|
|
var result = coder.decode([ 'bool' ], '0x');
|
|
|
|
console.log(result);
|
|
|
|
}, function(error) {
|
2018-04-17 04:42:17 +03:00
|
|
|
assert.equal(error.reason, 'insufficient data for boolean type', 'got invalid bool');
|
2018-03-18 00:39:45 +03:00
|
|
|
return true;
|
|
|
|
}, 'null bytes throws an error');
|
|
|
|
});
|
2018-07-27 01:02:42 +03:00
|
|
|
|
|
|
|
it('fails to encode fixed bytes that are out of range', function() {
|
|
|
|
assert.throws(function() {
|
|
|
|
var result = coder.encode([ 'bytes32' ], [ '0x012345678901234567890123456789012345678901234567890123456789012345' ]);
|
|
|
|
console.log('Result', result);
|
|
|
|
}, function(error) {
|
|
|
|
assert.equal(error.reason, 'invalid bytes32 value', 'got invalid bytes32');
|
|
|
|
return true;
|
|
|
|
}, 'long bytes32 throws an error');
|
|
|
|
});
|
|
|
|
|
2018-09-20 18:55:27 +03:00
|
|
|
// See: https://github.com/ethers-io/ethers.js/issues/281
|
|
|
|
it('fails to encode byteXX with odd input', function() {
|
|
|
|
assert.throws(function() {
|
|
|
|
var coder = ethers.utils.AbiCoder.defaultCoder;
|
|
|
|
var result = coder.encode([ 'bytes32' ], [ '0x1' ]);
|
|
|
|
console.log(result);
|
|
|
|
}, function(error) {
|
|
|
|
assert.equal(error.message, 'hex string cannot be odd-length', 'got odd bytes');
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-03-18 00:39:45 +03:00
|
|
|
});
|
2018-09-20 18:55:27 +03:00
|
|
|
|