pull/454/head
ioedeveloper 4 years ago
commit c027b3915a
  1. 4
      apps/remix-ide-e2e/src/commands/testFunction.ts
  2. 67
      apps/remix-ide-e2e/src/examples/example-contracts.ts
  3. 4
      apps/remix-ide-e2e/src/tests/ballot.test.ts
  4. 167
      apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts
  5. 28
      apps/remix-ide-e2e/src/tests/debugger.test.ts
  6. 4
      apps/remix-ide-e2e/src/tests/runAndDeploy.ts
  7. 8
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  8. 47
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  9. 4
      apps/remix-ide-e2e/src/tests/txListener.test.ts
  10. 9
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  11. 12
      apps/remix-ide/src/app.js
  12. 2
      apps/remix-ide/src/app/compiler/compiler-input.js
  13. 2
      apps/remix-ide/src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js
  14. 2
      apps/remix-ide/src/app/files/fileProvider.js
  15. 2
      apps/remix-ide/src/app/tabs/debugger/debuggerUI/VmDebugger.js
  16. 7
      apps/remix-ide/src/app/ui/landing-page/landing-page.js
  17. 5
      apps/remix-ide/src/blockchain/blockchain.js
  18. 4
      apps/remix-ide/src/lib/offsetToLineColumnConverter.js
  19. 8
      apps/remix-ide/src/remixAppManager.js
  20. 10
      libs/remix-analyzer/src/types.ts
  21. 198
      libs/remix-astwalker/src/astWalker.ts
  22. 9
      libs/remix-astwalker/src/types.ts
  23. 101
      libs/remix-astwalker/tests/LegacyTest.ts
  24. 71
      libs/remix-astwalker/tests/newTests.ts
  25. 2
      libs/remix-astwalker/tests/resources/legacyAST.ts
  26. 2
      libs/remix-debug/bin/rdb
  27. 2
      libs/remix-debug/test.js
  28. 2
      libs/remix-debug/test/helpers/compilerHelper.js
  29. 19
      libs/remix-lib/src/execution/eventsDecoder.js
  30. 2
      libs/remix-lib/src/execution/execution-context.js
  31. 3
      libs/remix-lib/src/execution/txHelper.js
  32. 2
      libs/remix-lib/src/execution/txRunner.js
  33. 2
      libs/remix-lib/src/helpers/compilerHelper.js
  34. 10
      libs/remix-lib/src/web3Provider/web3VmProvider.js
  35. 33
      libs/remix-simulator/src/methods/debug.js
  36. 3
      libs/remix-simulator/src/methods/transactions.js
  37. 2
      libs/remix-simulator/src/provider.js
  38. 2
      libs/remix-solidity/src/compiler/compiler-input.ts
  39. 12
      libs/remix-solidity/src/compiler/types.ts
  40. 10
      libs/remix-tests/src/types.ts
  41. 884
      package-lock.json
  42. 3
      package.json

@ -48,9 +48,9 @@ class TestFunction extends EventEmitter {
const equal: boolean = deepequal(logs[key], expectedValue[key]) const equal: boolean = deepequal(logs[key], expectedValue[key])
if (!equal) { if (!equal) {
browser.assert.fail(`Expected ${expectedValue[key]} but got ${logs[key]}`) browser.assert.fail(`Expected ${JSON.stringify(expectedValue[key])} but got ${JSON.stringify(logs[key])}`)
} else { } else {
browser.assert.ok(true, `Expected value matched returned value ${expectedValue[key]}`) browser.assert.ok(true, `Expected value matched returned value ${JSON.stringify(expectedValue[key])}`)
} }
}) })
this.emit('complete') this.emit('complete')

@ -215,6 +215,72 @@ contract Ballot {
} }
` `
const ballot_0_4_11 = `pragma solidity >=0.4.10 <0.7.0;
contract Ballot {
struct Voter {
uint weight;
bool voted;
uint8 vote;
address delegate;
}
struct Proposal {
uint voteCount;
}
address chairperson;
mapping(address => Voter) voters;
Proposal[] proposals;
/// Create a new ballot with $(_numProposals) different proposals.
function Ballot (uint8 _numProposals) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
proposals.length = _numProposals;
}
/// Give $(toVoter) the right to vote on this ballot.
/// May only be called by $(chairperson).
function giveRightToVote(address toVoter) public {
if (msg.sender != chairperson || voters[toVoter].voted) return;
voters[toVoter].weight = 1;
}
/// Delegate your vote to the voter $(to).
function delegate(address to) public {
Voter storage sender = voters[msg.sender]; // assigns reference
if (sender.voted) return;
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate;
if (to == msg.sender) return;
sender.voted = true;
sender.delegate = to;
Voter storage delegateTo = voters[to];
if (delegateTo.voted)
proposals[delegateTo.vote].voteCount += sender.weight;
else
delegateTo.weight += sender.weight;
}
/// Give a single vote to proposal $(toProposal).
function vote(uint8 toProposal) public {
Voter storage sender = voters[msg.sender];
if (sender.voted || toProposal >= proposals.length) return;
sender.voted = true;
sender.vote = toProposal;
proposals[toProposal].voteCount += sender.weight;
}
function winningProposal() public returns (uint8 _winningProposal) {
uint256 winningVoteCount = 0;
for (uint8 prop = 0; prop < proposals.length; prop++)
if (proposals[prop].voteCount > winningVoteCount) {
winningVoteCount = proposals[prop].voteCount;
_winningProposal = prop;
}
}
}`
const ballotTest = `pragma solidity >=0.4.22 <0.7.0; const ballotTest = `pragma solidity >=0.4.22 <0.7.0;
import "remix_tests.sol"; // this import is automatically injected by Remix. import "remix_tests.sol"; // this import is automatically injected by Remix.
import "../3_Ballot.sol"; import "../3_Ballot.sol";
@ -245,5 +311,6 @@ export default {
storage: { name: '1_Storage.sol', content: storage }, storage: { name: '1_Storage.sol', content: storage },
owner: { name: '2_Owner.sol', content: owner }, owner: { name: '2_Owner.sol', content: owner },
ballot: { name: '3_Ballot.sol', content: ballot }, ballot: { name: '3_Ballot.sol', content: ballot },
ballot_0_4_11: { name: 'ballot_0_4_11.sol', content: ballot_0_4_11 },
ballot_test: { name: 'tests/4_Ballot_test.sol', content: ballotTest } ballot_test: { name: 'tests/4_Ballot_test.sol', content: ballotTest }
} }

@ -30,7 +30,7 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}) .clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'})
.testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3', .testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3', 'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
}) })
@ -62,7 +62,7 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}) .clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'})
.testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803', .testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
{ {
status: '0x0 Transaction mined but execution failed', status: 'false Transaction mined but execution failed',
'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803', 'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
}) })

@ -0,0 +1,167 @@
'use strict'
import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
import sauce from './sauce'
import examples from '../examples/example-contracts'
const sources = [
{'browser/Untitled.sol': { content: examples.ballot_0_4_11.content }}
]
module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, null, false)
},
'@sources': function () {
return sources
},
'Compile Ballot with compiler version 0.4.11': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.4.11+commit.68ef5810.js')
.waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]')
.verify.elementPresent('[data-id="compilerContainerAutoCompile"]:checked')
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
},
'Deploy Ballot': function (browser: NightwatchBrowser) {
browser.pause(500)
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
.setValue('input[placeholder="uint8 _numProposals"]', '2')
.click('*[data-id="Deploy - transact (not payable)"]')
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]')
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'})
.testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},
'Debug Ballot / delegate': function (browser: NightwatchBrowser) {
browser.pause(500)
.click('*[data-id="txLoggerDebugButton0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3"]')
.pause(2000)
.click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.pause(2000)
.goToVMTraceStep(20)
.pause(1000)
.checkVariableDebug('callstackpanel', ["0x692a70D2e424a56D2C6C27aA97D1a86395877b3A"])
},
'Access Ballot via at address': function (browser: NightwatchBrowser) {
browser.clickLaunchIcon('udapp')
.click('*[data-id="universalDappUiUdappClose"]')
.addFile('ballot.abi', { content: ballotABI })
.addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3B', true, false)
.clickLaunchIcon('fileExplorers')
.addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3A', true, true)
.pause(500)
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]')
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'})
.testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
{
status: 'true Transaction mined and execution succeed',
'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
})
},
'Deploy and use Ballot using external web3': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="settingsWeb3Mode"]')
.modalFooterOKClick()
.clickLaunchIcon('solidity')
.testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
.setValue('input[placeholder="uint8 _numProposals"]', '2')
.click('*[data-id="Deploy - transact (not payable)"]')
.clickInstance(0)
.click('*[data-id="terminalClearConsole"]')
.clickFunction('delegate - transact (not payable)', {types: 'address to', values: '0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c'})
.journalLastChildIncludes('Ballot.delegate(address)')
.journalLastChildIncludes('data: 0x5c1...a733c')
.end()
},
tearDown: sauce
}
const ballotABI = `[
{
"constant": false,
"inputs": [
{
"name": "to",
"type": "address"
}
],
"name": "delegate",
"outputs": [],
"payable": false,
"type": "function",
"stateMutability": "nonpayable"
},
{
"constant": false,
"inputs": [],
"name": "winningProposal",
"outputs": [
{
"name": "_winningProposal",
"type": "uint8"
}
],
"payable": false,
"type": "function",
"stateMutability": "nonpayable"
},
{
"constant": false,
"inputs": [
{
"name": "toVoter",
"type": "address"
}
],
"name": "giveRightToVote",
"outputs": [],
"payable": false,
"type": "function",
"stateMutability": "nonpayable"
},
{
"constant": false,
"inputs": [
{
"name": "toProposal",
"type": "uint8"
}
],
"name": "vote",
"outputs": [],
"payable": false,
"type": "function",
"stateMutability": "nonpayable"
},
{
"inputs": [
{
"name": "_numProposals",
"type": "uint8"
}
],
"payable": false,
"type": "constructor",
"stateMutability": "nonpayable"
}
]`

@ -72,7 +72,28 @@ module.exports = {
.click('*[data-id="buttonNavigatorJumpNextBreakpoint"]') .click('*[data-id="buttonNavigatorJumpNextBreakpoint"]')
.pause(2000) .pause(2000)
.assert.containsText('*[data-id="stepdetail"]', 'vm trace step:\n184') .assert.containsText('*[data-id="stepdetail"]', 'vm trace step:\n184')
.assert.containsText('*[data-id="stepdetail"]', 'execution step:\n184') .assert.containsText('*[data-id="stepdetail"]', 'execution step:\n184')
},
'Should display solidity imported code while debugging github import': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.6.12+commit.27d51765.js')
.clickLaunchIcon('udapp')
.testContracts('externalImport.sol', sources[1]['browser/externalImport.sol'], ['ERC20'])
.selectContract('ERC20')
.createContract('"tokenName", "symbol"')
.debugTransaction(2)
.pause(2000)
.goToVMTraceStep(10)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
_decimals = 18;
}`) != -1,
'current displayed content is not from the ERC20 source code')
})
.end() .end()
}, },
@ -112,5 +133,10 @@ const sources = [
} }
` `
} }
},
{
'browser/externalImport.sol': {content: 'import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol"; contract test7 {}'}
} }
] ]

@ -48,7 +48,7 @@ module.exports = {
.click('*[data-id="Deploy - transact (not payable)"]') .click('*[data-id="Deploy - transact (not payable)"]')
.pause(5000) .pause(5000)
.testFunction('0xc39ee005c1e1368c84f02e458de4b41dbb966631a8714d15ef8362dada249ede', { .testFunction('0xc39ee005c1e1368c84f02e458de4b41dbb966631a8714d15ef8362dada249ede', {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0xc39ee005c1e1368c84f02e458de4b41dbb966631a8714d15ef8362dada249ede' 'transaction hash': '0xc39ee005c1e1368c84f02e458de4b41dbb966631a8714d15ef8362dada249ede'
}) })
}, },
@ -61,7 +61,7 @@ module.exports = {
.click('*[data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"]') .click('*[data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"]')
.pause(5000) .pause(5000)
.testFunction('0xfe718871ee0b4d03cdcac0e12e5b164efaf7e23ba952c07db76e62692867019b', { .testFunction('0xfe718871ee0b4d03cdcac0e12e5b164efaf7e23ba952c07db76e62692867019b', {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0xfe718871ee0b4d03cdcac0e12e5b164efaf7e23ba952c07db76e62692867019b' 'transaction hash': '0xfe718871ee0b4d03cdcac0e12e5b164efaf7e23ba952c07db76e62692867019b'
}) })
}, },

@ -59,7 +59,13 @@ module.exports = {
.pause(5000) .pause(5000)
.executeScript(`remix.execute('browser/asyncAwaitWithFileManagerAccess.js')`) .executeScript(`remix.execute('browser/asyncAwaitWithFileManagerAccess.js')`)
.pause(6000) .pause(6000)
.journalLastChildIncludes('contract Ballot {') .journalLastChildIncludes('contract Ballot {')
},
'Call web3.eth.getAccounts() using JavaScript VM': function (browser: NightwatchBrowser) {
browser
.executeScript(`web3.eth.getAccounts()`)
.journalLastChildIncludes(`[ "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4", "0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2", "0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db", "0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB", "0x617F2E2fD72FD9D5503197092aC168c91465E7f2", "0x17F6AD8Ef982297579C203069C1DbfFE4348c372", "0x5c6B0f7Bf3E7ce046039Bd8FABdfD3f9F5021678", "0x03C6FcED478cBbC9a4FAB34eF9f40767739D1Ff7", "0x1aE0EA34a72D944a8C7603FfB3eC30a6669E454C", "0x0A098Eda01Ce92ff4A4CCb7A4fFFb5A43EBC70DC", "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c", "0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C", "0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB", "0x583031D1113aD414F02576BD6afaBfb302140225", "0xdD870fA1b7C4700F2BD7f44238821C26f7392148" ]`)
.end() .end()
}, },

@ -23,7 +23,7 @@ module.exports = {
.clickFunction('f - transact (not payable)') .clickFunction('f - transact (not payable)')
.testFunction('0x38bb944fa4709ed9e163d6c670259f97284b4defd916d512a2fcc3f35bb53e03', .testFunction('0x38bb944fa4709ed9e163d6c670259f97284b4defd916d512a2fcc3f35bb53e03',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0x38bb944fa4709ed9e163d6c670259f97284b4defd916d512a2fcc3f35bb53e03', 'transaction hash': '0x38bb944fa4709ed9e163d6c670259f97284b4defd916d512a2fcc3f35bb53e03',
'decoded output': { '0': 'uint256: 8' } 'decoded output': { '0': 'uint256: 8' }
}) })
@ -32,7 +32,7 @@ module.exports = {
.clickFunction('g - transact (not payable)') .clickFunction('g - transact (not payable)')
.testFunction('0xab4f794ca0b531f27fc6eace623666b440facbf20e77615a057d728c67b500f0', .testFunction('0xab4f794ca0b531f27fc6eace623666b440facbf20e77615a057d728c67b500f0',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0xab4f794ca0b531f27fc6eace623666b440facbf20e77615a057d728c67b500f0', 'transaction hash': '0xab4f794ca0b531f27fc6eace623666b440facbf20e77615a057d728c67b500f0',
'decoded output': { 'decoded output': {
'0': 'uint256: 345', '0': 'uint256: 345',
@ -53,7 +53,7 @@ module.exports = {
.clickFunction('retunValues1 - transact (not payable)') .clickFunction('retunValues1 - transact (not payable)')
.testFunction('0x09c6716a67f0f8c7a0ca2b3ddf59c25982da856a95aefd640b767f9b9feee39d', .testFunction('0x09c6716a67f0f8c7a0ca2b3ddf59c25982da856a95aefd640b767f9b9feee39d',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0x09c6716a67f0f8c7a0ca2b3ddf59c25982da856a95aefd640b767f9b9feee39d', 'transaction hash': '0x09c6716a67f0f8c7a0ca2b3ddf59c25982da856a95aefd640b767f9b9feee39d',
'decoded output': { 'decoded output': {
'0': 'bool: _b true', '0': 'bool: _b true',
@ -65,7 +65,7 @@ module.exports = {
.clickFunction('retunValues2 - transact (not payable)') .clickFunction('retunValues2 - transact (not payable)')
.testFunction('0xe884953e0695399d60914af3e1ea2dad59fe41f3c0c20665c130fa40dd0fb6bf', .testFunction('0xe884953e0695399d60914af3e1ea2dad59fe41f3c0c20665c130fa40dd0fb6bf',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0xe884953e0695399d60914af3e1ea2dad59fe41f3c0c20665c130fa40dd0fb6bf', 'transaction hash': '0xe884953e0695399d60914af3e1ea2dad59fe41f3c0c20665c130fa40dd0fb6bf',
'decoded output': { 'decoded output': {
'0': 'bytes1: _b 0x12', '0': 'bytes1: _b 0x12',
@ -83,7 +83,7 @@ module.exports = {
.clickFunction('retunValues3 - transact (not payable)') .clickFunction('retunValues3 - transact (not payable)')
.testFunction('0xb4108649d5e65a4a0776d6ac98c2c356540a7e99d641705a82352a845d467eb5', .testFunction('0xb4108649d5e65a4a0776d6ac98c2c356540a7e99d641705a82352a845d467eb5',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0xb4108649d5e65a4a0776d6ac98c2c356540a7e99d641705a82352a845d467eb5', 'transaction hash': '0xb4108649d5e65a4a0776d6ac98c2c356540a7e99d641705a82352a845d467eb5',
'decoded output': { 'decoded output': {
'0': 'uint8: _en 2', '0': 'uint8: _en 2',
@ -101,7 +101,7 @@ module.exports = {
.clickFunction('inputValue1 - transact (not payable)', {types: 'uint256 _u, int256 _i, string _str', values: '"2343242", "-4324324", "string _ string _ string _ string _ string _ string _ string _ string _ string _ string _"'}) .clickFunction('inputValue1 - transact (not payable)', {types: 'uint256 _u, int256 _i, string _str', values: '"2343242", "-4324324", "string _ string _ string _ string _ string _ string _ string _ string _ string _ string _"'})
.testFunction('0xe9678b5486674a0425301a1d7e925c22cfb9f7f7ec6242697d742009f7ef5b97', .testFunction('0xe9678b5486674a0425301a1d7e925c22cfb9f7f7ec6242697d742009f7ef5b97',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0xe9678b5486674a0425301a1d7e925c22cfb9f7f7ec6242697d742009f7ef5b97', 'transaction hash': '0xe9678b5486674a0425301a1d7e925c22cfb9f7f7ec6242697d742009f7ef5b97',
'decoded output': { 'decoded output': {
'0': 'uint256: _uret 2343242', '0': 'uint256: _uret 2343242',
@ -112,7 +112,7 @@ module.exports = {
.pause(500) .pause(500)
.clickFunction('inputValue2 - transact (not payable)', {types: 'uint256[3] _n, bytes8[4] _b8', values: '[1,2,3], ["0x1234000000000000", "0x1234000000000000","0x1234000000000000","0x1234000000000000"]'}) .clickFunction('inputValue2 - transact (not payable)', {types: 'uint256[3] _n, bytes8[4] _b8', values: '[1,2,3], ["0x1234000000000000", "0x1234000000000000","0x1234000000000000","0x1234000000000000"]'})
.testFunction('0x21724b08c3699bda8375803f8dc842194aea370f2aac284e55144b452dca321f', { .testFunction('0x21724b08c3699bda8375803f8dc842194aea370f2aac284e55144b452dca321f', {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0x21724b08c3699bda8375803f8dc842194aea370f2aac284e55144b452dca321f', 'transaction hash': '0x21724b08c3699bda8375803f8dc842194aea370f2aac284e55144b452dca321f',
'decoded output': { 'decoded output': {
'0': 'uint256[3]: _nret 1,2,3', '0': 'uint256[3]: _nret 1,2,3',
@ -120,33 +120,32 @@ module.exports = {
}, },
logs: [ logs: [
{ {
'from': '0x8c1ed7e19abaa9f23c476da86dc1577f1ef401f5', 'from': '0x8c1eD7e19abAa9f23c476dA86Dc1577F1Ef401f5',
'topic': '0xd30981760edbf605bda8689e945f622877f230c9a77cbfbd448aa4b7d8ac6e7f', 'topic': '0xd30981760edbf605bda8689e945f622877f230c9a77cbfbd448aa4b7d8ac6e7f',
'event': 'event1', 'event': 'event1',
'args': { 'args': {
'0': '-123', '0': '-123',
'1': '123', '1': '123',
'2': { '2': {
'hash': '0x9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658', "_isIndexed":true,
'type': 'Indexed' 'hash': '0x9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658'
}, },
'3': '0x12340000', '3': '0x12340000',
'4': 'test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test ', '4': 'test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test '
'_i': '-123',
'_u': '123',
'_str': {
'hash': '0x9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658',
'type': 'Indexed'
},
'_b': '0x12340000',
'_notIndexed': 'test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test ',
'length': 5
} }
} }
] ]
}) })
.click('*[data-id="deployAndRunClearInstances"]') .click('*[data-id="deployAndRunClearInstances"]')
.end() },
'Should Compile and Deploy a contract which has an event declaring a function as parameter': function (browser: NightwatchBrowser) {
browser.testContracts('eventFunctionInput.sol', sources[3]['browser/eventFunctionInput.sol'], ['C'])
.clickLaunchIcon('udapp')
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
.click('#runTabView button[class^="instanceButton"]')
.waitForElementPresent('.instance:nth-of-type(2)')
.end()
}, },
tearDown: sauce tearDown: sauce
@ -207,5 +206,11 @@ const sources = [
_b8ret = _b8; _b8ret = _b8;
emit event1(-123, 123, "test", hex"1234", "test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test "); emit event1(-123, 123, "test", hex"1234", "test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test ");
} }
}`}},
// https://github.com/ethereum/remix-project/issues/404
{'browser/eventFunctionInput.sol': {content: `
pragma solidity >= 0.7.0;
contract C {
event Test(function() external);
}`}} }`}}
] ]

@ -31,7 +31,7 @@ module.exports = {
.clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}) .clickFunction('delegate - transact (not payable)', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'})
.testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3', .testFunction('0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
{ {
status: '0x1 Transaction mined and execution succeed', status: 'true Transaction mined and execution succeed',
'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3', 'transaction hash': '0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
}) })
@ -42,7 +42,7 @@ module.exports = {
.pause(5000) .pause(5000)
.testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803', .testFunction('0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
{ {
status: '0x0 Transaction mined but execution failed', status: 'false Transaction mined but execution failed',
'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803', 'transaction hash': '0xca58080c8099429caeeffe43b8104df919c2c543dceb9edf9242fa55f045c803',
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' } 'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
}) })

@ -5,7 +5,7 @@ import sauce from './sauce'
module.exports = { module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080?plugins=solidity,udapp&plugincall=fileManager//open//3_Ballot.sol', false) init(browser, done, 'http://127.0.0.1:8080?activate=solidity,udapp&call=fileManager//open//3_Ballot.sol&deactivate=home', false)
}, },
'CheckSolidityActivatedAndUDapp': function (browser: NightwatchBrowser) { 'CheckSolidityActivatedAndUDapp': function (browser: NightwatchBrowser) {
@ -20,7 +20,12 @@ module.exports = {
.pause(5000) .pause(5000)
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content.indexOf('contract Ballot {') != -1, 'content doesn\'t include Ballot contract') browser.assert.ok(content.indexOf('contract Ballot {') != -1, 'content doesn\'t include Ballot contract')
}) })
},
'Home page should be deactivated': function (browser: NightwatchBrowser) {
browser
.waitForElementNotPresent('[data-id="landingPageHomeContainer"]')
.end() .end()
}, },

@ -405,11 +405,19 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// Set workspace after initial activation // Set workspace after initial activation
if (Array.isArray(workspace)) { if (Array.isArray(workspace)) {
appManager.activatePlugin(workspace).then(() => { appManager.activatePlugin(workspace).then(() => {
try {
if (params.deactivate) {
appManager.deactivatePlugin(params.deactivate.split(','))
}
} catch (e) {
console.log(e)
}
// If plugins are loaded from the URL params, we focus on the last one. // If plugins are loaded from the URL params, we focus on the last one.
if (pluginLoader.current === 'queryParams' && workspace.length > 0) menuicons.select(workspace[workspace.length - 1]) if (pluginLoader.current === 'queryParams' && workspace.length > 0) menuicons.select(workspace[workspace.length - 1])
if (params.plugincall) { if (params.call) {
const callDetails = params.plugincall.split('//') const callDetails = params.call.split('//')
if (callDetails.length > 1) { if (callDetails.length > 1) {
toolTip(`initiating ${callDetails[0]} ...`) toolTip(`initiating ${callDetails[0]} ...`)
// @todo(remove the timeout when activatePlugin is on 0.3.0) // @todo(remove the timeout when activatePlugin is on 0.3.0)

@ -12,7 +12,7 @@ module.exports = (sources, opts) => {
libraries: opts.libraries, libraries: opts.libraries,
outputSelection: { outputSelection: {
'*': { '*': {
'': [ 'legacyAST', 'ast'], '': [ 'ast'],
'*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] '*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ]
} }
} }

@ -69,7 +69,7 @@ export default class FetchAndCompile extends Plugin {
} }
let name = network.name.toLowerCase() let name = network.name.toLowerCase()
name === 'main' ? 'mainnet' : name // source-verifier api expect "mainnet" and not "main" name = name === 'main' ? 'mainnet' : name // source-verifier api expect "mainnet" and not "main"
let data let data
try { try {
data = await this.call('source-verification', 'fetchByNetwork', contractAddress, name.toLowerCase()) data = await this.call('source-verification', 'fetchByNetwork', contractAddress, name.toLowerCase())

@ -70,6 +70,7 @@ class FileProvider {
} }
_exists (path) { _exists (path) {
path = this.getPathFromUrl(path) || path // ensure we actually use the normalized path from here
var unprefixedpath = this.removePrefix(path) var unprefixedpath = this.removePrefix(path)
return path === this.type ? true : window.remixFileSystem.existsSync(unprefixedpath) return path === this.type ? true : window.remixFileSystem.existsSync(unprefixedpath)
} }
@ -148,6 +149,7 @@ class FileProvider {
} }
isFile (path) { isFile (path) {
path = this.getPathFromUrl(path) || path // ensure we actually use the normalized path from here
path = this.removePrefix(path) path = this.removePrefix(path)
return window.remixFileSystem.statSync(path).isFile() return window.remixFileSystem.statSync(path).isFile()
} }

@ -38,7 +38,7 @@ function VmDebugger (vmDebuggerLogic) {
this.functionPanel = new FunctionPanel() this.functionPanel = new FunctionPanel()
this.vmDebuggerLogic.event.register('functionsStackUpdate', (stack) => { this.vmDebuggerLogic.event.register('functionsStackUpdate', (stack) => {
if (stack === null) return if (stack === null || stack.length === 0) return
let functions = [] let functions = []
for (let func of stack) { for (let func of stack) {
functions.push(func.functionDefinition.name + '(' + func.inputs.join(', ') + ')') functions.push(func.functionDefinition.name + '(' + func.inputs.join(', ') + ')')

@ -61,6 +61,9 @@ let css = csjs`
.labelIt { .labelIt {
margin-bottom: 0; margin-bottom: 0;
} }
.bigLabelSize {
font-size: 13px;
}
.seeAll { .seeAll {
margin-top: 7px; margin-top: 7px;
white-space: nowrap; white-space: nowrap;
@ -374,7 +377,7 @@ export class LandingPage extends ViewPlugin {
</p> </p>
<p class="mb-1"> <p class="mb-1">
<i class="mr-1 far fa-file-alt"></i> <i class="mr-1 far fa-file-alt"></i>
<span class="ml-1 ${css.labelIt} ${css.text}"> <label class="ml-1 ${css.labelIt} ${css.bigLabelSize} ${css.text}">
Open Files Open Files
<input title="open file" type="file" onchange="${ <input title="open file" type="file" onchange="${
(event) => { (event) => {
@ -383,7 +386,7 @@ export class LandingPage extends ViewPlugin {
fileExplorer.uploadFile(event) fileExplorer.uploadFile(event)
} }
}" multiple /> }" multiple />
</span> </label>
</p> </p>
<p class="mb-1"> <p class="mb-1">
<i class="far fa-hdd"></i> <i class="far fa-hdd"></i>

@ -228,6 +228,11 @@ class Blockchain {
} }
web3 () { web3 () {
// @todo(https://github.com/ethereum/remix-project/issues/431)
const isVM = this.getProvider() === 'vm'
if (isVM) {
return this.providers.vm.web3
}
return this.executionContext.web3() return this.executionContext.web3()
} }

@ -20,8 +20,8 @@ export class OffsetToLineColumnConverter extends Plugin {
offsetToLineColumn (rawLocation, file, sources, asts) { offsetToLineColumn (rawLocation, file, sources, asts) {
if (!this.lineBreakPositionsByContent[file]) { if (!this.lineBreakPositionsByContent[file]) {
const sourcesArray = Object.keys(sources) const sourcesArray = Object.keys(sources)
if (!asts && file === 0 && sourcesArray.length === 1) { if (!asts || (file === 0 && sourcesArray.length === 1)) {
// if we don't have ast, we process the only one available content // if we don't have ast, we process the only one available content (applicable also for compiler older than 0.4.12)
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[sourcesArray[0]].content) this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[sourcesArray[0]].content)
} else { } else {
for (var filename in asts) { for (var filename in asts) {

@ -135,13 +135,13 @@ class PluginLoader {
this.loaders['queryParams'] = { this.loaders['queryParams'] = {
set: () => {}, set: () => {},
get: () => { get: () => {
const { plugins } = queryParams.get() const { activate } = queryParams.get()
if (!plugins) return [] if (!activate) return []
return plugins.split(',') return activate.split(',')
} }
} }
this.current = queryParams.get()['plugins'] ? 'queryParams' : 'localStorage' this.current = queryParams.get()['activate'] ? 'queryParams' : 'localStorage'
} }
set (plugin, actives) { set (plugin, actives) {

@ -720,8 +720,6 @@ export interface CommonYulAstNode {
id: number id: number
/** The AST object */ /** The AST object */
ast: AstNode ast: AstNode
/** The legacy AST object */
legacyAST: AstNodeLegacy
} }
///////// /////////
@ -742,14 +740,6 @@ export interface CommonYulAstNode {
[x: string]: any [x: string]: any
} }
export interface AstNodeLegacy {
id: number
name: string
src: string
children?: Array<AstNodeLegacy>
attributes?: AstNodeAtt
}
export interface AstNodeAtt { export interface AstNodeAtt {
operator?: string operator?: string
string?: null string?: null

@ -1,5 +1,5 @@
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { AstNodeLegacy, Node, AstNode } from "./index"; import { Node, AstNode } from "./index";
export declare interface AstWalker { export declare interface AstWalker {
new(): EventEmitter; new(): EventEmitter;
@ -34,16 +34,16 @@ export function isAstNode(node: Record<string, unknown>): boolean {
*/ */
export class AstWalker extends EventEmitter { export class AstWalker extends EventEmitter {
manageCallback( manageCallback(
node: AstNodeLegacy | AstNode, node: AstNode,
callback: Record<string, unknown> | Function // eslint-disable-line @typescript-eslint/ban-types callback: Record<string, unknown> | Function // eslint-disable-line @typescript-eslint/ban-types
): any { ): any {
// FIXME: we shouldn't be doing this callback determination type on each AST node, // FIXME: we shouldn't be doing this callback determination type on each AST node,
// since the callback function is set once per walk. // since the callback function is set once per walk.
// Better would be to store the right one as a variable and // Better would be to store the right one as a variable and
// return that. // return that.
if (<AstNodeLegacy>node) { if (node) {
if ((<AstNodeLegacy>node).name in callback) { if ((node).name in callback) {
return callback[(<AstNodeLegacy>node).name](node); return callback[(node).name](node);
} else { } else {
return callback["*"](node); return callback["*"](node);
} }
@ -58,67 +58,148 @@ export class AstWalker extends EventEmitter {
} }
} }
} }
normalizeNodes(nodes: AstNode[]): AstNode[] {
// Remove null, undefined and empty elements if any
nodes = nodes.filter(e => e)
// If any element in nodes is array, extract its members
const objNodes = []
nodes.forEach(x => {
if (Array.isArray(x)) objNodes.push(...x)
else objNodes.push(x)
});
// Filter duplicate nodes using id field
const normalizedNodes = []
objNodes.forEach((element) => {
const firstIndex = normalizedNodes.findIndex(e => e.id === element.id)
if(firstIndex == -1) normalizedNodes.push(element)
})
return normalizedNodes
}
getASTNodeChildren(ast: AstNode): AstNode[] {
let nodes = ast.nodes // for ContractDefinition
|| ast.body // for FunctionDefinition, ModifierDefinition, WhileStatement, DoWhileStatement, ForStatement
|| ast.statements // for Block, YulBlock
|| ast.members // for StructDefinition, EnumDefinition
|| ast.overrides // for OverrideSpecifier
|| ast.parameters // for ParameterList, EventDefinition
|| ast.declarations // for VariableDeclarationStatement
|| ast.expression // for Return, ExpressionStatement, FunctionCall, FunctionCallOptions, MemberAccess
|| ast.components // for TupleExpression
|| ast.subExpression // for UnaryOperation
|| ast.eventCall // for EmitStatement
|| []
// If 'nodes' is not an array, convert it into one, for example: ast.body
if(nodes && !Array.isArray(nodes)) {
const tempArr = []
tempArr.push(nodes)
nodes = tempArr
}
// To break object referencing
nodes = [...nodes]
if(ast.nodes && ast.baseContracts?.length) { // for ContractDefinition
nodes.push(...ast.baseContracts)
} else if (ast.body && ast.overrides && ast.parameters && ast.returnParameters && ast.modifiers) { // for FunctionDefinition
nodes.push(ast.overrides)
nodes.push(ast.parameters)
nodes.push(ast.returnParameters)
nodes.push(ast.modifiers)
} else if(ast.typeName) { // for VariableDeclaration, NewExpression, ElementaryTypeNameExpression
nodes.push(ast.typeName)
} else if (ast.body && ast.overrides && ast.parameters) { // for ModifierDefinition
nodes.push(ast.overrides)
nodes.push(ast.parameters)
} else if (ast.modifierName && ast.arguments) { // for ModifierInvocation
nodes.push(ast.modifierName)
nodes.push(ast.arguments)
} else if (ast.parameterTypes && ast.returnParameterTypes) { // for ModifierInvocation
nodes.push(ast.parameterTypes)
nodes.push(ast.returnParameterTypes)
} else if (ast.keyType && ast.valueType) { // for Mapping
nodes.push(ast.keyType)
nodes.push(ast.valueType)
} else if (ast.baseType && ast.length) { // for ArrayTypeName
nodes.push(ast.baseType)
nodes.push(ast.length)
} else if (ast.AST) { // for InlineAssembly
nodes.push(ast.AST)
} else if (ast.condition && (ast.trueBody || ast.falseBody || ast.body)) { // for IfStatement, WhileStatement, DoWhileStatement
nodes.push(ast.condition)
nodes.push(ast.trueBody)
nodes.push(ast.falseBody)
} else if (ast.parameters && ast.block) { // for TryCatchClause
nodes.push(ast.block)
} else if (ast.externalCall && ast.clauses) { // for TryStatement
nodes.push(ast.externalCall)
nodes.push(ast.clauses)
} else if (ast.body && ast.condition && ast.initializationExpression && ast.loopExpression) { // for ForStatement
nodes.push(ast.condition)
nodes.push(ast.initializationExpression)
nodes.push(ast.loopExpression)
} else if (ast.declarations && ast.initialValue) { // for VariableDeclarationStatement
nodes.push(ast.initialValue)
} else if (ast.condition && (ast.trueExpression || ast.falseExpression)) { // for Conditional
nodes.push(ast.condition)
nodes.push(ast.trueExpression)
nodes.push(ast.falseExpression)
} else if (ast.leftHandSide && ast.rightHandSide) { // for Assignment
nodes.push(ast.leftHandSide)
nodes.push(ast.rightHandSide)
} else if (ast.leftExpression && ast.rightExpression) { // for BinaryOperation
nodes.push(ast.leftExpression)
nodes.push(ast.rightExpression)
} else if (ast.expression && (ast.arguments || ast.options)) { // for FunctionCall, FunctionCallOptions
nodes.push(ast.arguments ? ast.arguments : ast.options)
} else if (ast.baseExpression && (ast.indexExpression || (ast.startExpression && ast.endExpression))) { // for IndexAccess, IndexRangeAccess
nodes.push(ast.baseExpression)
if(ast.indexExpression) nodes.push(ast.indexExpression)
else {
nodes.push(ast.startExpression)
nodes.push(ast.endExpression)
}
}
return this.normalizeNodes(nodes)
}
// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types
walk(ast: AstNodeLegacy | AstNode, callback?: Function | Record<string, unknown>) { walk(ast: AstNode, callback?: Function | Record<string, unknown>) {
if (callback) { if (ast) {
if (callback instanceof Function) { const children: AstNode[] = this.getASTNodeChildren(ast)
callback = Object({ "*": callback }); if (callback) {
} if (callback instanceof Function) {
if (!("*" in callback)) { callback = Object({ "*": callback });
callback["*"] = function() {
return true;
};
}
if (<AstNodeLegacy>ast) {
if (
this.manageCallback(<AstNodeLegacy>ast, callback) &&
(<AstNodeLegacy>ast).children &&
(<AstNodeLegacy>ast).children.length > 0
) {
for (const k in (<AstNodeLegacy>ast).children) {
const child = (<AstNodeLegacy>ast).children[k];
this.walk(child, callback);
}
} }
} else if (<AstNode>ast) { if (!("*" in callback)) {
if ( callback["*"] = function() {
this.manageCallback(<AstNode>ast, callback) && return true;
(<AstNode>ast).nodes && };
(<AstNode>ast).nodes.length > 0
) {
for (const k in (<AstNode>ast).nodes) {
const child = (<AstNode>ast).nodes[k];
this.walk(child, callback);
}
} }
} if (this.manageCallback(ast, callback) && children?.length) {
} else { for (const k in children) {
if (<AstNodeLegacy>ast) { const child = children[k];
if ( this.walk(child, callback);
(<AstNodeLegacy>ast).children &&
(<AstNodeLegacy>ast).children.length > 0
) {
for (const k in (<AstNodeLegacy>ast).children) {
const child = (<AstNodeLegacy>ast).children[k];
this.emit("node", child);
this.walk(child);
} }
} }
} } else {
if (<AstNode>ast) { if (children?.length) {
if ((<AstNode>ast).nodes && (<AstNode>ast).nodes.length > 0) { for (const k in children) {
for (const k in (<AstNode>ast).nodes) { const child = children[k];
const child = (<AstNode>ast).nodes[k]; this.emit("node", child);
this.emit("node", child); this.walk(child);
this.walk(child); }
} }
} }
}
} }
} }
// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types
walkFullInternal(ast: AstNode, callback: Function) { walkFullInternal(ast: AstNode, callback: Function) {
if (isAstNode(ast)) { if (isAstNode(ast)) {
// console.log(`XXX id ${ast.id}, nodeType: ${ast.nodeType}, src: ${ast.src}`); // console.log(`XXX id ${ast.id}, nodeType: ${ast.nodeType}, src: ${ast.src}`);
callback(ast); callback(ast);
@ -142,8 +223,7 @@ export class AstWalker extends EventEmitter {
// Normalizes parameter callback and calls walkFullInternal // Normalizes parameter callback and calls walkFullInternal
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
walkFull(ast: AstNode, callback: any) { walkFull(ast: AstNode, callback: any) {
if (!isAstNode(ast)) throw new TypeError("first argument should be an ast"); if (isAstNode(ast)) return this.walkFullInternal(ast, callback);
return this.walkFullInternal(ast, callback);
} }
// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/explicit-module-boundary-types
@ -151,14 +231,10 @@ export class AstWalker extends EventEmitter {
if (cb) { if (cb) {
if (sourcesList.ast) { if (sourcesList.ast) {
this.walk(sourcesList.ast, cb); this.walk(sourcesList.ast, cb);
} else {
this.walk(sourcesList.legacyAST, cb);
} }
} else { } else {
if (sourcesList.ast) { if (sourcesList.ast) {
this.walk(sourcesList.ast); this.walk(sourcesList.ast);
} else {
this.walk(sourcesList.legacyAST);
} }
} }
} }

@ -24,7 +24,6 @@ export interface LineColRange {
export interface Node { export interface Node {
ast?: AstNode; ast?: AstNode;
legacyAST?: AstNodeLegacy;
source?: string; source?: string;
id?: number; id?: number;
} }
@ -47,14 +46,6 @@ export interface AstNode {
[x: string]: any; [x: string]: any;
} }
export interface AstNodeLegacy {
id: number; // This is unique across all nodes in an AST tree
name: string; // This corresponds to "nodeType" in ASTNode
src: string;
children?: Array<AstNodeLegacy>; // This corresponds to "nodes" in ASTNode
attributes?: AstNodeAtt;
}
export interface AstNodeAtt { export interface AstNodeAtt {
operator?: string; operator?: string;
string?: null; string?: null;

@ -1,101 +0,0 @@
import tape from "tape";
import { AstWalker, AstNodeLegacy } from "../src";
import node from "./resources/legacyAST";
tape("ASTWalker Legacy", (t: tape.Test) => {
t.test("ASTWalker.walk && .walkAST", (st: tape.Test) => {
st.plan(17);
// New Ast Object
const astWalker = new AstWalker();
// EventListener
astWalker.on("node", node => {
if (node.name === "ContractDefinition") {
checkContract(st, node);
}
if (node.name === "FunctionDefinition") {
checkSetFunction(st, node);
checkGetFunction(st, node);
}
if (node.name === "VariableDeclaration") {
checkSetFunction(st, node);
checkGetFunction(st, node);
}
});
// Callback pattern
astWalker.walk(node.legacyAST, (node: AstNodeLegacy) => {
if (node.name === "ContractDefinition") {
checkContract(st, node);
}
if (node.name === "FunctionDefinition") {
checkSetFunction(st, node);
checkGetFunction(st, node);
}
if (node.name === "VariableDeclaration") {
checkSetFunction(st, node);
checkGetFunction(st, node);
}
});
// Callback Object
var callback: any = {};
callback.FunctionDefinition = function(node: AstNodeLegacy): boolean {
st.equal(node.name, "FunctionDefinition");
return true;
};
// Calling walk function with cb
astWalker.walk(node.legacyAST, callback);
// Calling walk function without cb
astWalker.walk(node.legacyAST);
// Calling WALKASTLIST function
astWalker.walkAstList(node);
// Calling walkASTList with new AST format
astWalker.walkAstList(node);
// Calling WALKASTLIST function with cb
astWalker.walkAstList(node, node => {
return true;
});
st.end();
});
});
function checkContract(st: tape.Test, node: AstNodeLegacy) {
st.equal(node.attributes.name, "Greeter");
st.equal(node.children[1].attributes.name, "greeting");
st.equal(node.children[1].attributes.type, "string");
st.equal(node.children[2].name, "FunctionDefinition");
st.equal(node.children[2].attributes.name, "");
}
function checkSetFunction(st: tape.Test, node: AstNodeLegacy) {
if (node.attributes.name === "set") {
st.equal(node.children[0].name, "ParameterList");
st.equal(node.children[1].name, "ParameterList");
st.equal(node.children[2].name, "Block");
st.equal(node.children[2].children[1].name, "ExpressionStatement");
checkExpressionStatement(st, node.children[2].children[0]);
}
}
function checkGetFunction(st: tape.Test, node: AstNodeLegacy) {
if (node.attributes.name === "get") {
st.equal(node.children[0].name, "ParameterList");
st.equal(node.children[1].name, "ParameterList");
st.equal(node.children[2].name, "Block");
}
}
function checkExpressionStatement(st: tape.Test, node: AstNodeLegacy) {
st.equal(node.children[0].name, "Assignment");
st.equal(node.children[0].attributes.operator, "=");
st.equal(node.children[0].attributes.type, "int256");
st.equal(node.children[0].children[0].name, "Identifier");
st.equal(node.children[0].children[0].attributes.value, "x");
st.equal(node.children[0].children[1].name, "Identifier");
st.equal(node.children[0].children[1].attributes.value, "_x");
}

@ -6,7 +6,9 @@ import legacyNode from "./resources/legacyAST";
tape("New ASTWalker", (t: tape.Test) => { tape("New ASTWalker", (t: tape.Test) => {
// New Ast Object // New Ast Object
const astWalker = new AstWalker(); const astWalker = new AstWalker();
const latestASTNode = JSON.parse(JSON.stringify(node.ast))
t.test("ASTWalker.walk && .walkastList", (st: tape.Test) => { t.test("ASTWalker.walk && .walkastList", (st: tape.Test) => {
const latestAST = JSON.parse(JSON.stringify(latestASTNode))
st.plan(24); st.plan(24);
// EventListener // EventListener
astWalker.on("node", node => { astWalker.on("node", node => {
@ -20,7 +22,7 @@ tape("New ASTWalker", (t: tape.Test) => {
}); });
// Callback pattern // Callback pattern
astWalker.walk(node.ast, (node: AstNode) => { astWalker.walk(latestAST, (node: AstNode) => {
if (node.nodeType === "ContractDefinition") { if (node.nodeType === "ContractDefinition") {
checkContract(st, node); checkContract(st, node);
} }
@ -38,10 +40,10 @@ tape("New ASTWalker", (t: tape.Test) => {
return true; return true;
}; };
// Calling walk function with cb // Calling walk function with cb
astWalker.walk(node.ast, callback); astWalker.walk(latestAST, callback);
// Calling walk function without cb // Calling walk function without cb
astWalker.walk(node.ast); astWalker.walk(latestAST);
// Calling WALKASTLIST function // Calling WALKASTLIST function
astWalker.walkAstList(node); astWalker.walkAstList(node);
@ -52,11 +54,72 @@ tape("New ASTWalker", (t: tape.Test) => {
}); });
st.end(); st.end();
}); });
t.test("ASTWalker.getASTNodeChildren", (st: tape.Test) => {
const latestAST = JSON.parse(JSON.stringify(latestASTNode))
st.plan(26);
st.equal(latestAST.nodeType, 'SourceUnit')
let subNodes1 = astWalker.getASTNodeChildren(latestAST)
st.equal(subNodes1.length, 3)
st.equal(subNodes1[0].nodeType, 'PragmaDirective')
st.equal(subNodes1[1].nodeType, 'ImportDirective')
st.equal(subNodes1[2].nodeType, 'ContractDefinition')
let subNodes2 = astWalker.getASTNodeChildren(subNodes1[0])
st.equal(subNodes2.length, 0)
subNodes2 = astWalker.getASTNodeChildren(subNodes1[1])
st.equal(subNodes2.length, 0)
subNodes2 = astWalker.getASTNodeChildren(subNodes1[2])
st.equal(subNodes2.length, 4)
st.equal(subNodes2[0].nodeType, 'VariableDeclaration')
st.equal(subNodes2[1].nodeType, 'FunctionDefinition')
st.equal(subNodes2[2].nodeType, 'FunctionDefinition')
st.equal(subNodes2[3].nodeType, 'InheritanceSpecifier')
let subNodes3 = astWalker.getASTNodeChildren(subNodes2[0])
st.equal(subNodes3.length, 1)
st.equal(subNodes3[0].nodeType, 'ElementaryTypeName')
let subNodes4 = astWalker.getASTNodeChildren(subNodes3[0])
st.equal(subNodes4.length, 0)
subNodes3 = astWalker.getASTNodeChildren(subNodes2[1])
st.equal(subNodes3.length, 1)
st.equal(subNodes3[0].nodeType, 'Block')
subNodes4 = astWalker.getASTNodeChildren(subNodes3[0])
st.equal(subNodes4.length, 1)
st.equal(subNodes4[0].nodeType, 'ExpressionStatement')
let subNodes5 = astWalker.getASTNodeChildren(subNodes4[0])
st.equal(subNodes5.length, 1)
st.equal(subNodes5[0].nodeType, 'Assignment')
let subNodes6 = astWalker.getASTNodeChildren(subNodes5[0])
st.equal(subNodes6.length, 2)
st.equal(subNodes6[0].nodeType, 'Identifier')
st.equal(subNodes6[1].nodeType, 'Identifier')
let subNodes7 = astWalker.getASTNodeChildren(subNodes6[0])
st.equal(subNodes7.length, 0)
subNodes7 = astWalker.getASTNodeChildren(subNodes6[1])
st.equal(subNodes7.length, 0)
st.end();
});
t.test("ASTWalkFull", (st: tape.Test) => { t.test("ASTWalkFull", (st: tape.Test) => {
const latestAST = JSON.parse(JSON.stringify(latestASTNode))
const astNodeCount = 26; const astNodeCount = 26;
st.plan(2 + astNodeCount); st.plan(2 + astNodeCount);
let count: number = 0; let count: number = 0;
astWalker.walkFull(node.ast, (node: AstNode) => { astWalker.walkFull(latestAST, (node: AstNode) => {
st.ok(isAstNode(node), "passed an ast node"); st.ok(isAstNode(node), "passed an ast node");
count += 1; count += 1;
}); });

@ -1,5 +1,5 @@
import { Node } from '../../src/' import { Node } from '../../src/'
let node: Node; let node: any;
node = { "legacyAST": { "children": [{ "attributes": { "literals": ["solidity", ">=", "0.5", ".0", "<", "0.6", ".0"] }, "id": 1, "name": "PragmaDirective", "src": "0:31:0" }, { "attributes": { "SourceUnit": 53, "absolutePath": "mortal.sol", "file": "mortal.sol", "scope": 26, "symbolAliases": [null], "unitAlias": "" }, "id": 2, "name": "ImportDirective", "src": "32:20:0" }, { "attributes": { "contractDependencies": [52], "contractKind": "contract", "documentation": null, "fullyImplemented": true, "linearizedBaseContracts": [25, 52], "name": "Greeter", "scope": 26 }, "children": [{ "attributes": { "arguments": null }, "children": [{ "attributes": { "contractScope": null, "name": "Mortal", "referencedDeclaration": 52, "type": "contract Mortal" }, "id": 3, "name": "UserDefinedTypeName", "src": "74:6:0" }], "id": 4, "name": "InheritanceSpecifier", "src": "74:6:0" }, { "attributes": { "constant": false, "name": "greeting", "scope": 25, "stateVariable": true, "storageLocation": "default", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 5, "name": "ElementaryTypeName", "src": "141:6:0" }], "id": 6, "name": "VariableDeclaration", "src": "141:15:0" }, { "attributes": { "documentation": null, "implemented": true, "isConstructor": true, "kind": "constructor", "modifiers": [null], "name": "", "scope": 25, "stateMutability": "nonpayable", "superFunction": null, "visibility": "public" }, "children": [{ "children": [{ "attributes": { "constant": false, "name": "_greeting", "scope": 16, "stateVariable": false, "storageLocation": "memory", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 7, "name": "ElementaryTypeName", "src": "225:6:0" }], "id": 8, "name": "VariableDeclaration", "src": "225:23:0" }], "id": 9, "name": "ParameterList", "src": "224:25:0" }, { "attributes": { "parameters": [null] }, "children": [], "id": 10, "name": "ParameterList", "src": "257:0:0" }, { "children": [{ "children": [{ "attributes": { "argumentTypes": null, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "operator": "=", "type": "string storage ref" }, "children": [{ "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 6, "type": "string storage ref", "value": "greeting" }, "id": 11, "name": "Identifier", "src": "267:8:0" }, { "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 8, "type": "string memory", "value": "_greeting" }, "id": 12, "name": "Identifier", "src": "278:9:0" }], "id": 13, "name": "Assignment", "src": "267:20:0" }], "id": 14, "name": "ExpressionStatement", "src": "267:20:0" }], "id": 15, "name": "Block", "src": "257:37:0" }], "id": 16, "name": "FunctionDefinition", "src": "213:81:0" }, { "attributes": { "documentation": null, "implemented": true, "isConstructor": false, "kind": "function", "modifiers": [null], "name": "greet", "scope": 25, "stateMutability": "view", "superFunction": null, "visibility": "public" }, "children": [{ "attributes": { "parameters": [null] }, "children": [], "id": 17, "name": "ParameterList", "src": "338:2:0" }, { "children": [{ "attributes": { "constant": false, "name": "", "scope": 24, "stateVariable": false, "storageLocation": "memory", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 18, "name": "ElementaryTypeName", "src": "362:6:0" }], "id": 19, "name": "VariableDeclaration", "src": "362:13:0" }], "id": 20, "name": "ParameterList", "src": "361:15:0" }, { "children": [{ "attributes": { "functionReturnParameters": 20 }, "children": [{ "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 6, "type": "string storage ref", "value": "greeting" }, "id": 21, "name": "Identifier", "src": "394:8:0" }], "id": 22, "name": "Return", "src": "387:15:0" }], "id": 23, "name": "Block", "src": "377:32:0" }], "id": 24, "name": "FunctionDefinition", "src": "324:85:0" }], "id": 25, "name": "ContractDefinition", "src": "54:357:0" }], "name": "SourceUnit", "attributes": { "absolutePath": "greeter.sol", "exportedSymbols": { "Greeter": [25] } }, "id": 26, "src": "0:412:0" } } node = { "legacyAST": { "children": [{ "attributes": { "literals": ["solidity", ">=", "0.5", ".0", "<", "0.6", ".0"] }, "id": 1, "name": "PragmaDirective", "src": "0:31:0" }, { "attributes": { "SourceUnit": 53, "absolutePath": "mortal.sol", "file": "mortal.sol", "scope": 26, "symbolAliases": [null], "unitAlias": "" }, "id": 2, "name": "ImportDirective", "src": "32:20:0" }, { "attributes": { "contractDependencies": [52], "contractKind": "contract", "documentation": null, "fullyImplemented": true, "linearizedBaseContracts": [25, 52], "name": "Greeter", "scope": 26 }, "children": [{ "attributes": { "arguments": null }, "children": [{ "attributes": { "contractScope": null, "name": "Mortal", "referencedDeclaration": 52, "type": "contract Mortal" }, "id": 3, "name": "UserDefinedTypeName", "src": "74:6:0" }], "id": 4, "name": "InheritanceSpecifier", "src": "74:6:0" }, { "attributes": { "constant": false, "name": "greeting", "scope": 25, "stateVariable": true, "storageLocation": "default", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 5, "name": "ElementaryTypeName", "src": "141:6:0" }], "id": 6, "name": "VariableDeclaration", "src": "141:15:0" }, { "attributes": { "documentation": null, "implemented": true, "isConstructor": true, "kind": "constructor", "modifiers": [null], "name": "", "scope": 25, "stateMutability": "nonpayable", "superFunction": null, "visibility": "public" }, "children": [{ "children": [{ "attributes": { "constant": false, "name": "_greeting", "scope": 16, "stateVariable": false, "storageLocation": "memory", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 7, "name": "ElementaryTypeName", "src": "225:6:0" }], "id": 8, "name": "VariableDeclaration", "src": "225:23:0" }], "id": 9, "name": "ParameterList", "src": "224:25:0" }, { "attributes": { "parameters": [null] }, "children": [], "id": 10, "name": "ParameterList", "src": "257:0:0" }, { "children": [{ "children": [{ "attributes": { "argumentTypes": null, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "operator": "=", "type": "string storage ref" }, "children": [{ "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 6, "type": "string storage ref", "value": "greeting" }, "id": 11, "name": "Identifier", "src": "267:8:0" }, { "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 8, "type": "string memory", "value": "_greeting" }, "id": 12, "name": "Identifier", "src": "278:9:0" }], "id": 13, "name": "Assignment", "src": "267:20:0" }], "id": 14, "name": "ExpressionStatement", "src": "267:20:0" }], "id": 15, "name": "Block", "src": "257:37:0" }], "id": 16, "name": "FunctionDefinition", "src": "213:81:0" }, { "attributes": { "documentation": null, "implemented": true, "isConstructor": false, "kind": "function", "modifiers": [null], "name": "greet", "scope": 25, "stateMutability": "view", "superFunction": null, "visibility": "public" }, "children": [{ "attributes": { "parameters": [null] }, "children": [], "id": 17, "name": "ParameterList", "src": "338:2:0" }, { "children": [{ "attributes": { "constant": false, "name": "", "scope": 24, "stateVariable": false, "storageLocation": "memory", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 18, "name": "ElementaryTypeName", "src": "362:6:0" }], "id": 19, "name": "VariableDeclaration", "src": "362:13:0" }], "id": 20, "name": "ParameterList", "src": "361:15:0" }, { "children": [{ "attributes": { "functionReturnParameters": 20 }, "children": [{ "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 6, "type": "string storage ref", "value": "greeting" }, "id": 21, "name": "Identifier", "src": "394:8:0" }], "id": 22, "name": "Return", "src": "387:15:0" }], "id": 23, "name": "Block", "src": "377:32:0" }], "id": 24, "name": "FunctionDefinition", "src": "324:85:0" }], "id": 25, "name": "ContractDefinition", "src": "54:357:0" }], "name": "SourceUnit", "attributes": { "absolutePath": "greeter.sol", "exportedSymbols": { "Greeter": [25] } }, "id": 26, "src": "0:412:0" } }

@ -44,7 +44,7 @@ const inputJson = {
}, },
outputSelection: { outputSelection: {
'*': { '*': {
'': [ 'legacyAST' ], '': [ 'ast' ],
'*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] '*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ]
} }
} }

@ -19,7 +19,7 @@ var inputJson = {
}, },
outputSelection: { outputSelection: {
'*': { '*': {
'': [ 'legacyAST' ], '': [ 'ast' ],
'*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] '*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ]
} }
} }

@ -17,7 +17,7 @@ function compilerInput (contracts) {
}, },
outputSelection: { outputSelection: {
'*': { '*': {
'': [ 'legacyAST', 'ast' ], '': [ 'ast' ],
'*': [ 'abi', 'metadata', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] '*': [ 'abi', 'metadata', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ]
} }
} }

@ -40,8 +40,8 @@ class EventsDecoder {
const eventABI = {} const eventABI = {}
const abi = new ethers.utils.Interface(contract.abi) const abi = new ethers.utils.Interface(contract.abi)
for (let e in abi.events) { for (let e in abi.events) {
const event = abi.events[e] const event = abi.getEvent(e)
eventABI[event.topic.replace('0x', '')] = { event: event.name, inputs: event.inputs, object: event, abi: abi } eventABI[abi.getEventTopic(e).replace('0x', '')] = { event: event.name, inputs: event.inputs, object: event, abi: abi }
} }
return eventABI return eventABI
} }
@ -57,14 +57,21 @@ class EventsDecoder {
_event (hash, eventsABI) { _event (hash, eventsABI) {
for (let k in eventsABI) { for (let k in eventsABI) {
if (eventsABI[k][hash]) { if (eventsABI[k][hash]) {
return eventsABI[k][hash] let event = eventsABI[k][hash]
for (let input of event.inputs) {
if (input.type === 'function') {
input.type = 'bytes24'
input.baseType = 'bytes24'
}
}
return event
} }
} }
return null return null
} }
_stringifyBigNumber (value) { _stringifyBigNumber (value) {
return value._ethersType === 'BigNumber' ? value.toString() : value return value._isBigNumber ? value.toString() : value
} }
_stringifyEvent (value) { _stringifyEvent (value) {
@ -89,8 +96,8 @@ class EventsDecoder {
if (eventAbi) { if (eventAbi) {
const decodedlog = eventAbi.abi.parseLog(log) const decodedlog = eventAbi.abi.parseLog(log)
const decoded = {} const decoded = {}
for (const v in decodedlog.values) { for (const v in decodedlog.args) {
decoded[v] = this._stringifyEvent(decodedlog.values[v]) decoded[v] = this._stringifyEvent(decodedlog.args[v])
} }
events.push({ from: log.address, topic: topicId, event: eventAbi.event, args: decoded }) events.push({ from: log.address, topic: topicId, event: eventAbi.event, args: decoded })
} else { } else {

@ -91,10 +91,12 @@ function createVm (hardfork) {
} }
const vms = { const vms = {
/*
byzantium: createVm('byzantium'), byzantium: createVm('byzantium'),
constantinople: createVm('constantinople'), constantinople: createVm('constantinople'),
petersburg: createVm('petersburg'), petersburg: createVm('petersburg'),
istanbul: createVm('istanbul'), istanbul: createVm('istanbul'),
*/
muirGlacier: createVm('muirGlacier') muirGlacier: createVm('muirGlacier')
} }

@ -36,8 +36,7 @@ module.exports = {
encodeFunctionId: function (funABI) { encodeFunctionId: function (funABI) {
if (funABI.type === 'fallback' || funABI.type === 'receive') return '0x' if (funABI.type === 'fallback' || funABI.type === 'receive') return '0x'
let abi = new ethers.utils.Interface([funABI]) let abi = new ethers.utils.Interface([funABI])
abi = abi.functions[funABI.name] return abi.getSighash(funABI.name)
return abi.sighash
}, },
sortAbiFunction: function (contractabi) { sortAbiFunction: function (contractabi) {

@ -258,7 +258,7 @@ function run (self, tx, stamp, confirmationCb, gasEstimationForceSend, promptCb,
self.pendingTxs[stamp] = tx self.pendingTxs[stamp] = tx
self.execute(tx, confirmationCb, gasEstimationForceSend, promptCb, function(error, result) { self.execute(tx, confirmationCb, gasEstimationForceSend, promptCb, function(error, result) {
delete self.pendingTxs[stamp] delete self.pendingTxs[stamp]
callback(error, result) if (callback && typeof callback === 'function') callback(error, result)
if (self.queusTxs.length) { if (self.queusTxs.length) {
const next = self.queusTxs.pop() const next = self.queusTxs.pop()
run(self, next.tx, next.stamp, next.callback) run(self, next.tx, next.stamp, next.callback)

@ -17,7 +17,7 @@ function compilerInput (contracts) {
}, },
outputSelection: { outputSelection: {
'*': { '*': {
'': [ 'legacyAST', 'ast' ], '': [ 'ast' ],
'*': [ 'abi', 'metadata', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] '*': [ 'abi', 'metadata', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ]
} }
} }

@ -72,9 +72,9 @@ web3VmProvider.prototype.txWillProcess = function (self, data) {
} }
let tx = {} let tx = {}
tx.hash = self.processingHash tx.hash = self.processingHash
tx.from = util.hexConvert(data.getSenderAddress()) tx.from = ethutil.toChecksumAddress(util.hexConvert(data.getSenderAddress()))
if (data.to && data.to.length) { if (data.to && data.to.length) {
tx.to = util.hexConvert(data.to) tx.to = ethutil.toChecksumAddress(util.hexConvert(data.to))
} }
this.processingAddress = tx.to this.processingAddress = tx.to
tx.data = util.hexConvert(data.data) tx.data = util.hexConvert(data.data)
@ -128,8 +128,8 @@ web3VmProvider.prototype.txProcessed = function (self, data) {
if (data.createdAddress) { if (data.createdAddress) {
const address = util.hexConvert(data.createdAddress) const address = util.hexConvert(data.createdAddress)
self.vmTraces[self.processingHash].return = address self.vmTraces[self.processingHash].return = ethutil.toChecksumAddress(address)
self.txsReceipt[self.processingHash].contractAddress = address self.txsReceipt[self.processingHash].contractAddress = ethutil.toChecksumAddress(address)
} else if (data.execResult.returnValue) { } else if (data.execResult.returnValue) {
self.vmTraces[self.processingHash].return = util.hexConvert(data.execResult.returnValue) self.vmTraces[self.processingHash].return = util.hexConvert(data.execResult.returnValue)
} else { } else {
@ -196,6 +196,7 @@ web3VmProvider.prototype.pushTrace = function (self, data) {
} }
web3VmProvider.prototype.getCode = function (address, cb) { web3VmProvider.prototype.getCode = function (address, cb) {
address = ethutil.toChecksumAddress(address)
const account = ethutil.toBuffer(address) const account = ethutil.toBuffer(address)
this.vm.stateManager.getContractCode(account, (error, result) => { this.vm.stateManager.getContractCode(account, (error, result) => {
cb(error, util.hexConvert(result)) cb(error, util.hexConvert(result))
@ -219,6 +220,7 @@ web3VmProvider.prototype.traceTransaction = function (txHash, options, cb) {
web3VmProvider.prototype.storageRangeAt = function (blockNumber, txIndex, address, start, maxLength, cb) { // txIndex is the hash in the case of the VM web3VmProvider.prototype.storageRangeAt = function (blockNumber, txIndex, address, start, maxLength, cb) { // txIndex is the hash in the case of the VM
// we don't use the range params here // we don't use the range params here
address = ethutil.toChecksumAddress(address)
if (txIndex === 'latest') { if (txIndex === 'latest') {
txIndex = this.lastProcessedStorageTxHash[address] txIndex = this.lastProcessedStorageTxHash[address]

@ -0,0 +1,33 @@
class Debug {
constructor (executionContext) {
this.executionContext = executionContext
}
methods () {
return {
debug_traceTransaction: this.debug_traceTransaction.bind(this),
debug_preimage: this.debug_preimage.bind(this),
debug_storageRangeAt: this.debug_storageRangeAt.bind(this),
}
}
debug_traceTransaction (payload, cb) {
this.executionContext.web3().debug.traceTransaction(payload.params[0], {}, cb)
}
debug_preimage (payload, cb) {
this.executionContext.web3().debug.preimage(payload.params[0], cb)
}
debug_storageRangeAt (payload, cb) {
this.executionContext.web3().debug.storageRangeAt(
payload.params[0],
payload.params[1],
payload.params[2],
payload.params[3],
payload.params[4],
cb)
}
}
module.exports = Debug

@ -52,7 +52,8 @@ class Transactions{
'cumulativeGasUsed': Web3.utils.toHex(receipt.gas), 'cumulativeGasUsed': Web3.utils.toHex(receipt.gas),
'contractAddress': receipt.contractAddress, 'contractAddress': receipt.contractAddress,
'logs': receipt.logs, 'logs': receipt.logs,
'status': receipt.status 'status': receipt.status,
'to': receipt.to
} }
if (r.blockNumber === '0x') { if (r.blockNumber === '0x') {

@ -10,6 +10,7 @@ const Filters = require('./methods/filters.js')
const Misc = require('./methods/misc.js') const Misc = require('./methods/misc.js')
const Net = require('./methods/net.js') const Net = require('./methods/net.js')
const Transactions = require('./methods/transactions.js') const Transactions = require('./methods/transactions.js')
const Debug = require('./methods/debug.js')
const generateBlock = require('./genesis.js') const generateBlock = require('./genesis.js')
@ -28,6 +29,7 @@ class Provider {
this.methods = merge(this.methods, (new Filters(this.executionContext)).methods()) this.methods = merge(this.methods, (new Filters(this.executionContext)).methods())
this.methods = merge(this.methods, (new Net()).methods()) this.methods = merge(this.methods, (new Net()).methods())
this.methods = merge(this.methods, this.Transactions.methods()) this.methods = merge(this.methods, this.Transactions.methods())
this.methods = merge(this.methods, (new Debug(this.executionContext)).methods())
generateBlock(this.executionContext) generateBlock(this.executionContext)
this.init() this.init()

@ -14,7 +14,7 @@ export default (sources: Source, opts: CompilerInputOptions): string => {
libraries: opts.libraries, libraries: opts.libraries,
outputSelection: { outputSelection: {
'*': { '*': {
'': [ 'legacyAST', 'ast' ], '': [ 'ast' ],
'*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates', 'evm.assembly' ] '*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates', 'evm.assembly' ]
} }
} }

@ -122,7 +122,7 @@ export interface CompilerInput {
// //
outputSelection?: { outputSelection?: {
'*': { '*': {
'': [ 'legacyAST', 'ast' ], '': [ 'ast' ],
'*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates', 'evm.assembly' ] '*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates', 'evm.assembly' ]
} }
} }
@ -266,8 +266,6 @@ export interface CompilationResult {
id: number id: number
/** The AST object */ /** The AST object */
ast: AstNode ast: AstNode
/** The legacy AST object */
legacyAST: AstNodeLegacy
} }
///////// /////////
@ -288,14 +286,6 @@ export interface CompilationResult {
[x: string]: any [x: string]: any
} }
export interface AstNodeLegacy {
id: number
name: string
src: string
children?: Array<AstNodeLegacy>
attributes?: AstNodeAtt
}
export interface AstNodeAtt { export interface AstNodeAtt {
operator?: string operator?: string
string?: null string?: null

@ -81,16 +81,6 @@ export interface CompilationSource {
id: number id: number
/** The AST object */ /** The AST object */
ast: AstNode ast: AstNode
/** The legacy AST object */
legacyAST: AstNodeLegacy
}
export interface AstNodeLegacy {
id: number
name: string
src: string
children?: Array<AstNodeLegacy>
attributes?: AstNodeAtt
} }
export interface AstNodeAtt { export interface AstNodeAtt {

884
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -57,6 +57,7 @@
"nightwatch_local_firefox": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --env=firefox", "nightwatch_local_firefox": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --env=firefox",
"nightwatch_local_chrome": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --env=chrome", "nightwatch_local_chrome": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --env=chrome",
"nightwatch_local_ballot": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/ballot.test.js --env=chrome", "nightwatch_local_ballot": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/ballot.test.js --env=chrome",
"nightwatch_local_ballot_0_4_11": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.js --env=chrome",
"nightwatch_local_usingWorker": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/usingWebWorker.test.js --env=chrome", "nightwatch_local_usingWorker": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/usingWebWorker.test.js --env=chrome",
"nightwatch_local_libraryDeployment": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/libraryDeployment.test.js --env=chrome", "nightwatch_local_libraryDeployment": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/libraryDeployment.test.js --env=chrome",
"nightwatch_local_solidityImport": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/solidityImport.test.js --env=chrome", "nightwatch_local_solidityImport": "nx build remix-ide-e2e; nx e2e remix-ide-e2e --filePath=dist/apps/remix-ide-e2e/src/tests/solidityImport.test.js --env=chrome",
@ -209,7 +210,7 @@
"eslint": "6.8.0", "eslint": "6.8.0",
"eslint-config-prettier": "^6.11.0", "eslint-config-prettier": "^6.11.0",
"ethereumjs-util": "^6.2.0", "ethereumjs-util": "^6.2.0",
"ethers": "^4.0.27", "ethers": "^5.0.13",
"events": "^3.0.0", "events": "^3.0.0",
"execr": "^1.0.1", "execr": "^1.0.1",
"exorcist": "^0.4.0", "exorcist": "^0.4.0",

Loading…
Cancel
Save