'use strict' var tape = require('tape') var txFormat = require('../src/execution/txFormat') var txHelper = require('../src/execution/txHelper') var util = require('../src/util') var compiler = require('solc') var compilerInput = require('../src/helpers/compilerHelper').compilerInput var executionContext = require('../src/execution/execution-context') var solidityVersion = 'v0.5.11+commit.c082d0b4' /* tape *********************************************************** */ tape('load compiler ' + solidityVersion, function (t) { compiler.loadRemoteVersion(solidityVersion, (error, solcSnapshot) => { if (error) console.log(error) console.warn('testing *txFormat* against', solidityVersion) compiler = solcSnapshot t.end() }) }) var context tape('ContractParameters - (TxFormat.buildData) - format input parameters', function (t) { var output = compiler.compile(compilerInput(uintContract)) output = JSON.parse(output) var contract = output.contracts['test.sol']['uintContractTest'] context = { output, contract } t.test('(TxFormat.buildData)', function (st) { st.plan(3) testWithInput(st, '123123, "0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8", "34"', '000000000000000000000000000000000000000000000000000000000001e0f3000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea80000000000000000000000000000000000000000000000000000000000000022') testWithInput(st, '"123123" , 0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8, 654 ', '000000000000000000000000000000000000000000000000000000000001e0f3000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea8000000000000000000000000000000000000000000000000000000000000028e') // parsing this as javascript number should overflow testWithInput(st, '90071992547409910000, 0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8, 0', '000000000000000000000000000000000000000000000004e1ffffffffffd8f0000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea80000000000000000000000000000000000000000000000000000000000000000') }) }) function testWithInput (st, params, expected) { txFormat.buildData('uintContractTest', context.contract, context.output.contracts, true, context.contract.abi[0], params, (error, data) => { if (error) { return st.fails(error) } console.log(data) if (!data.dataHex.endsWith(expected)) { st.fail(`result of buildData ${data.dataHex} should end with ${expected} . `) } else { st.pass(`testWithInput. result of buildData ${data.dataHex} ends with correct data`) } }, () => {}, () => {}) } tape('ContractStringParameters - (TxFormat.buildData) - format string input parameters', function (t) { var output = compiler.compile(compilerInput(stringContract)) output = JSON.parse(output) console.log('-----------------------------', output) var contract = output.contracts['test.sol']['stringContractTest'] context = { output, contract } t.test('(TxFormat.buildData)', function (st) { st.plan(3) testWithStringInput(st, '"1,2,3,4qwerty,5", 0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8, "1,a,5,34"', '0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea800000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f312c322c332c347177657274792c3500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008312c612c352c3334000000000000000000000000000000000000000000000000') testWithStringInput(st, '"1,2,3,4qwerty,5", "0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8", "1,a,5,34"', '0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea800000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f312c322c332c347177657274792c3500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008312c612c352c3334000000000000000000000000000000000000000000000000') // string with space testWithStringInput(st, '"1,2,3,,4qw erty,5", "0xf7a10e525d4b168f45f74db1b61f63d3e7619ea8", "abcdefghijkl"', '0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000f7a10e525d4b168f45f74db1b61f63d3e7619ea800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000012312c322c332c2c3471772020657274792c350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6162636465666768696a6b6c0000000000000000000000000000000000000000') }) }) function testWithStringInput (st, params, expected) { txFormat.buildData('stringContractTest', context.contract, context.output.contracts, true, context.contract.abi[0], params, (error, data) => { if (error) { return st.fails(error) } console.log(data) if (!data.dataHex.endsWith(expected)) { st.fail(`result of buildData ${data.dataHex} should end with ${expected} . `) } else { st.pass(`testWithStringInput. result of buildData ${data.dataHex} ends with correct data`) } }, () => {}, () => {}) } /* tape *********************************************************** */ tape('ContractParameters - (TxFormat.buildData) - link Libraries', function (t) { executionContext.setContext('vm') var compileData = compiler.compile(compilerInput(deploySimpleLib)) var fakeDeployedContracts = { lib1: '0xf7a10e525d4b168f45f74db1b61f63d3e7619e11', lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2: '0xf7a10e525d4b168f45f74db1b61f63d3e7619e33', testContractLinkLibrary: '0xf7a10e525d4b168f45f74db1b61f63d3e7619e22' } var callbackDeployLibraries = (param, callback) => { callback(null, { result: { createdAddress: fakeDeployedContracts[param.data.contractName] } }) } // fake t.test('(TxFormat.buildData and link library (standard way))', function (st) { st.plan(6) var output = JSON.parse(compileData) var contract = output.contracts['test.sol']['testContractLinkLibrary'] context = { output, contract } testLinkLibrary(st, fakeDeployedContracts, callbackDeployLibraries) }) t.test('(TxFormat.encodeConstructorCallAndLinkLibraries and link library (standard way))', function (st) { st.plan(12) var output = JSON.parse(compileData) var contract = output.contracts['test.sol']['testContractLinkLibrary'] context = { output, contract } testLinkLibrary2(st, callbackDeployLibraries) }) }) function testLinkLibrary (st, fakeDeployedContracts, callbackDeployLibraries) { var deployMsg = ['creation of library test.sol:lib1 pending...', 'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...'] txFormat.buildData('testContractLinkLibrary', context.contract, context.output.contracts, true, context.contract.abi[0], '', (error, data) => { if (error) { return st.fails(error) } console.log(data) var linkedbyteCode = data.dataHex var libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib1'] st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), fakeDeployedContracts['lib1'].replace('0x', '')) st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), fakeDeployedContracts['lib1'].replace('0x', '')) libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'] st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), fakeDeployedContracts['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', '')) st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), fakeDeployedContracts['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', '')) }, (msg) => { st.equal(msg, deployMsg[0]) deployMsg.shift() }, callbackDeployLibraries) } function testLinkLibrary2 (st, callbackDeployLibraries) { var librariesReference = { 'test.sol': { 'lib1': '0xf7a10e525d4b168f45f74db1b61f63d3e7619e11', 'lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2': '0xf7a10e525d4b168f45f74db1b61f63d3e7619e33' } } var data = '608060405234801561001057600080fd5b506101e1806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80636d4ce63c14610030575b600080fd5b61003861003a565b005b73f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b15801561007e57600080fd5b505af4158015610092573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b1580156100da57600080fd5b505af41580156100ee573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e336344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b15801561013657600080fd5b505af415801561014a573d6000803e3d6000fd5b5050505073f7a10e525d4b168f45f74db1b61f63d3e7619e116344733ae16040518163ffffffff1660e01b815260040160006040518083038186803b15801561019257600080fd5b505af41580156101a6573d6000803e3d6000fd5b5050505056fea265627a7a72315820dd9fcfc020e6f69aedda5976b9a882d7955d9b71df3b292a57adddb96d0f7a2064736f6c634300050b0032' var deployMsg = ['creation of library test.sol:lib1 pending...', 'creation of library test.sol:lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 pending...'] txFormat.encodeConstructorCallAndLinkLibraries(context.contract, '', context.contract.abi[0], librariesReference, context.contract.evm.bytecode.linkReferences, (error, result) => { console.log(error, result) st.equal(data, result.dataHex) var linkedbyteCode = result.dataHex var libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib1'] st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib1'].replace('0x', '')) st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib1'].replace('0x', '')) libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'] st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', '')) st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', '')) }) txFormat.encodeConstructorCallAndDeployLibraries('testContractLinkLibrary', context.contract, context.output.contracts, '', context.contract.abi[0], (error, result) => { console.log(error, result) st.equal(data, result.dataHex) var linkedbyteCode = result.dataHex var libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib1'] st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib1'].replace('0x', '')) st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib1'].replace('0x', '')) libReference = context.contract.evm.bytecode.linkReferences['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'] st.equal(linkedbyteCode.substr(2 * libReference[0].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', '')) st.equal(linkedbyteCode.substr(2 * libReference[1].start, 40), librariesReference['test.sol']['lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2'].replace('0x', '')) }, (msg) => { st.equal(msg, deployMsg[0]) deployMsg.shift() }, callbackDeployLibraries) } /* tape *********************************************************** */ tape('EncodeParameter', function (t) { t.test('(TxFormat.encodeFunctionCall)', function (st) { st.plan(1) encodeFunctionCallTest(st) }) }) function encodeFunctionCallTest (st) { var output = compiler.compile(compilerInput(encodeFunctionCall)) output = JSON.parse(output) var contract = output.contracts['test.sol']['testContractLinkLibrary'] txFormat.encodeFunctionCall('123, "test string"', contract.abi[0], (error, encoded) => { console.log(error) st.equal(encoded.dataHex, '0x805da4ad000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b7465737420737472696e67000000000000000000000000000000000000000000') }) } /* *********************************************************** */ tape('test fallback function', function (t) { t.test('(fallback)', function (st) { st.plan(2) var output = compiler.compile(compilerInput(fallbackFunction)) output = JSON.parse(output) var contract = output.contracts['test.sol']['fallbackFunctionContract'] st.equal(txHelper.encodeFunctionId(contract.abi[0]), '0x805da4ad') st.equal(txHelper.encodeFunctionId(contract.abi[1]), '0x') }) }) tape('test abiEncoderV2', function (t) { var functionId = '0x56d89238' var encodedData = '0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000042ed123b0bd8203c2700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000090746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f746573745f737472696e675f00000000000000000000000000000000' var value1 = '1' var value2 = '1234567890123456789543' var value3 = 'test_string_test_string_test_string_test_string_test_string_test_string_test_string_test_string_test_string_test_string_test_string_test_string_' var decodedData = `[${value1}, ${value2}, "${value3}"], 23` t.test('(abiEncoderV2)', function (st) { st.plan(2) var output = compiler.compile(compilerInput(abiEncoderV2)) output = JSON.parse(output) var contract = output.contracts['test.sol']['test'] txFormat.encodeFunctionCall(decodedData, contract.abi[0], (error, encoded) => { console.log(error) st.equal(encoded.dataHex, functionId + encodedData.replace('0x', '')) }) var decoded = txFormat.decodeResponse(util.hexToIntArray(encodedData), contract.abi[0]) console.log(decoded) st.equal(decoded[0], `tuple(uint256,uint256,string): ${value1},${value2},${value3}`) }) }) tape('test abiEncoderV2 array of tuple', function (t) { t.test('(abiEncoderV2)', function (st) { /* { "685e37ad": "addStructs((uint256,string))", "e5cb65f9": "addStructs((uint256,string)[])" } */ st.plan(2) var output = compiler.compile(compilerInput(abiEncoderV2ArrayOfTuple)) output = JSON.parse(output) var contract = output.contracts['test.sol']['test'] txFormat.encodeParams('[34, "test"]', contract.abi[0], (error, encoded) => { console.log(error) var decoded = txFormat.decodeResponse(util.hexToIntArray(encoded.dataHex), contract.abi[0]) console.log(decoded) st.equal(decoded[0], 'tuple(uint256,string): _strucmts 34,test') }) txFormat.encodeParams('[[34, "test"], [123, "test2"]]', contract.abi[1], (error, encoded) => { console.log(error) var decoded = txFormat.decodeResponse(util.hexToIntArray(encoded.dataHex), contract.abi[1]) console.log(decoded) st.equal(decoded[0], 'tuple(uint256,string)[]: strucmts 34,test,123,test2') }) }) }) var uintContract = `contract uintContractTest { uint _tp; address _ap; function test(uint _t, address _a, uint _i) public { _tp = _t; _ap = _a; } }` var stringContract = `contract stringContractTest { string _tp; address _ap; function test(string memory _t, address _a, string memory _i) public { _tp = _t; _ap = _a; } }` var deploySimpleLib = `pragma solidity ^0.5.0; library lib1 { function getEmpty () public { } } library lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2 { function getEmpty () public { } } contract testContractLinkLibrary { function get () public { lib1.getEmpty(); lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2.getEmpty(); lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2_lib2.getEmpty(); lib1.getEmpty(); } }` var encodeFunctionCall = `pragma solidity ^0.5.0; contract testContractLinkLibrary { function get (uint _p, string memory _o) public { } }` var fallbackFunction = `pragma solidity ^0.5.0; contract fallbackFunctionContract { function get (uint _p, string memory _o) public { } function () external {} }` var abiEncoderV2 = `pragma experimental ABIEncoderV2; contract test { struct p { uint a; uint b; string s; } function t (p memory _p, uint _i) public returns (p memory) { return _p; } function t () public returns (p memory) { p memory mm; mm.a = 123; mm.b = 133; return mm; } }` var abiEncoderV2ArrayOfTuple = `pragma experimental ABIEncoderV2; contract test { struct MyStruct {uint256 num; string _string;} constructor (MyStruct[] memory _structs, string memory _str) public { } function addStructs(MyStruct[] memory _structs) public returns (MyStruct[] memory strucmts) { strucmts = _structs; } function addStructs(MyStruct memory _structs) public returns (MyStruct memory _strucmts) { _strucmts = _structs; } }`