Skip to content

Commit 8c5ee47

Browse files
authored
Merge branch 'master' into fix-upload
2 parents 2066213 + 9fb6f32 commit 8c5ee47

File tree

5 files changed

+102
-53
lines changed

5 files changed

+102
-53
lines changed

apps/remix-ide-e2e/src/commands/clickInstance.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class ClickInstance extends EventEmitter {
66
index = index + 2
77
const selector = '.instance:nth-of-type(' + index + ') > div > button'
88

9-
this.api.waitForElementContainsText(selector, '', 60000).scrollAndClick(selector).perform(() => { this.emit('complete') })
9+
this.api.waitForElementPresent(selector).waitForElementContainsText(selector, '', 60000).scrollAndClick(selector).perform(() => { this.emit('complete') })
1010
return this
1111
}
1212
}

apps/remix-ide-e2e/src/tests/transactionExecution.spec.ts

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,15 @@ module.exports = {
137137
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
138138
.click('#runTabView button[class^="instanceButton"]')
139139
.waitForElementPresent('.instance:nth-of-type(2)')
140+
.click('*[data-id="deployAndRunClearInstances"]')
140141
},
141142

142143
'Should Compile and Deploy a contract which define a custom error, the error should be logged in the terminal': function (browser: NightwatchBrowser) {
143144
browser.testContracts('customError.sol', sources[4]['customError.sol'], ['C'])
144145
.clickLaunchIcon('udapp')
145146
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
146147
.click('#runTabView button[class^="instanceButton"]')
147-
.waitForElementPresent('.instance:nth-of-type(3)')
148-
.click('.instance:nth-of-type(3) > div > button')
148+
.clickInstance(0)
149149
.clickFunction('g - transact (not payable)')
150150
.pause(5000)
151151
.journalLastChildIncludes('Error provided by the contract:')
@@ -158,15 +158,15 @@ module.exports = {
158158
.journalLastChildIncludes('"documentation": "param2"')
159159
.journalLastChildIncludes('"documentation": "param3"')
160160
.journalLastChildIncludes('Debug the transaction to get more information.')
161+
.click('*[data-id="deployAndRunClearInstances"]')
161162
},
162163

163164
'Should Compile and Deploy a contract which define a custom error, the error should be logged in the terminal , using London VM Fork': function (browser: NightwatchBrowser) {
164165
browser
165166
.click('*[data-id="settingsVMLondonMode"]') // switch to London fork
166167
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite
167168
.click('#runTabView button[class^="instanceButton"]')
168-
.waitForElementPresent('.instance:nth-of-type(2)')
169-
.click('.instance:nth-of-type(2) > div > button')
169+
.clickInstance(0)
170170
.clickFunction('g - transact (not payable)')
171171
.journalLastChildIncludes('Error provided by the contract:')
172172
.journalLastChildIncludes('CustomError : error description')
@@ -178,6 +178,25 @@ module.exports = {
178178
.journalLastChildIncludes('"documentation": "param2"')
179179
.journalLastChildIncludes('"documentation": "param3"')
180180
.journalLastChildIncludes('Debug the transaction to get more information.')
181+
},
182+
183+
'Should Compile and Deploy a contract which define a custom error in a library, the error should be logged in the terminal': function (browser: NightwatchBrowser) {
184+
browser.testContracts('customErrorLib.sol', sources[5]['customErrorLib.sol'], ['D'])
185+
.clickLaunchIcon('udapp')
186+
.click('#runTabView button[class^="instanceButton"]')
187+
.clickInstance(1)
188+
.clickFunction('h - transact (not payable)')
189+
.pause(5000)
190+
.journalLastChildIncludes('Error provided by the contract:')
191+
.journalLastChildIncludes('CustomError : error description from library')
192+
.journalLastChildIncludes('Parameters:')
193+
.journalLastChildIncludes('"value": "48"')
194+
.journalLastChildIncludes('"value": "46"')
195+
.journalLastChildIncludes('"value": "error_string_from_library"')
196+
.journalLastChildIncludes('"documentation": "param1 from library"')
197+
.journalLastChildIncludes('"documentation": "param2 from library"')
198+
.journalLastChildIncludes('"documentation": "param3 from library"')
199+
.journalLastChildIncludes('Debug the transaction to get more information.')
181200
.end()
182201
}
183202
}
@@ -281,5 +300,29 @@ contract C {
281300
}
282301
}`
283302
}
303+
},
304+
{
305+
'customErrorLib.sol': {
306+
content: `// SPDX-License-Identifier: GPL-3.0
307+
308+
pragma solidity ^0.8.7;
309+
310+
library lib {
311+
/// error description from library
312+
/// @param a param1 from library
313+
/// @param b param2 from library
314+
/// @param c param3 from library
315+
error CustomError(uint a, uint b, string c);
316+
function set() public {
317+
revert CustomError(48, 46, "error_string_from_library");
318+
}
319+
}
320+
321+
contract D {
322+
function h() public {
323+
lib.set();
324+
}
325+
}`
326+
}
284327
}
285328
]

apps/remix-ide/src/blockchain/blockchain.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,8 @@ class Blockchain extends Plugin {
524524
if (execResult) {
525525
// if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value.
526526
returnValue = execResult ? execResult.returnValue : toBuffer(addHexPrefix(txResult.result) || '0x0000000000000000000000000000000000000000000000000000000000000000')
527-
const vmError = txExecution.checkVMError(execResult, args.data.contractABI, args.data.contract)
527+
const compiledContracts = await this.call('compilerArtefacts', 'getAllContractDatas')
528+
const vmError = txExecution.checkVMError(execResult, compiledContracts)
528529
if (vmError.error) {
529530
return cb(vmError.message)
530531
}

libs/remix-core-plugin/src/lib/compiler-artefacts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { CompilerAbstract } from '@remix-project/remix-solidity'
44

55
const profile = {
66
name: 'compilerArtefacts',
7-
methods: ['get', 'addResolvedContract', 'getCompilerAbstract'],
7+
methods: ['get', 'addResolvedContract', 'getCompilerAbstract', 'getAllContractDatas'],
88
events: [],
99
version: '0.0.1'
1010
}

libs/remix-lib/src/execution/txExecution.ts

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function callFunction (from, to, data, value, gasLimit, funAbi, txRunner,
5757
* @param {Object} execResult - execution result given by the VM
5858
* @return {Object} - { error: true/false, message: DOMNode }
5959
*/
60-
export function checkVMError (execResult, abi, contract) {
60+
export function checkVMError (execResult, compiledContracts) {
6161
const errorCode = {
6262
OUT_OF_GAS: 'out of gas',
6363
STACK_UNDERFLOW: 'stack underflow',
@@ -91,55 +91,60 @@ export function checkVMError (execResult, abi, contract) {
9191
const returnData = execResult.returnValue
9292
const returnDataHex = returnData.slice(0, 4).toString('hex')
9393
let customError
94-
if (abi) {
94+
if (compiledContracts) {
9595
let decodedCustomErrorInputsClean
96-
for (const item of abi) {
97-
if (item.type === 'error') {
98-
// ethers doesn't crash anymore if "error" type is specified, but it doesn't extract the errors. see:
99-
// https://github.com/ethers-io/ethers.js/commit/bd05aed070ac9e1421a3e2bff2ceea150bedf9b7
100-
// we need here to fake the type, so the "getSighash" function works properly
101-
const fn = getFunctionFragment({ ...item, type: 'function', stateMutability: 'nonpayable' })
102-
if (!fn) continue
103-
const sign = fn.getSighash(item.name)
104-
if (!sign) continue
105-
if (returnDataHex === sign.replace('0x', '')) {
106-
customError = item.name
107-
const functionDesc = fn.getFunction(item.name)
108-
// decoding error parameters
109-
const decodedCustomErrorInputs = fn.decodeFunctionData(functionDesc, returnData)
110-
decodedCustomErrorInputsClean = {}
111-
let devdoc = {}
112-
// "contract" reprensents the compilation result containing the NATSPEC documentation
113-
if (contract && fn.functions && Object.keys(fn.functions).length) {
114-
const functionSignature = Object.keys(fn.functions)[0]
115-
// we check in the 'devdoc' if there's a developer documentation for this error
116-
try {
117-
devdoc = (contract.object.devdoc.errors && contract.object.devdoc.errors[functionSignature][0]) || {}
118-
} catch (e) {
119-
console.error(e.message)
120-
}
121-
// we check in the 'userdoc' if there's an user documentation for this error
122-
try {
123-
const userdoc = (contract.object.userdoc.errors && contract.object.userdoc.errors[functionSignature][0]) || {}
124-
if (userdoc && (userdoc as any).notice) customError += ' : ' + (userdoc as any).notice // we append the user doc if any
125-
} catch (e) {
126-
console.error(e.message)
127-
}
128-
}
129-
let inputIndex = 0
130-
for (const input of functionDesc.inputs) {
131-
const inputKey = input.name || inputIndex
132-
const v = decodedCustomErrorInputs[inputKey]
96+
for (const file of Object.keys(compiledContracts)) {
97+
for (const contractName of Object.keys(compiledContracts[file])) {
98+
const contract = compiledContracts[file][contractName]
99+
for (const item of contract.abi) {
100+
if (item.type === 'error') {
101+
// ethers doesn't crash anymore if "error" type is specified, but it doesn't extract the errors. see:
102+
// https://github.com/ethers-io/ethers.js/commit/bd05aed070ac9e1421a3e2bff2ceea150bedf9b7
103+
// we need here to fake the type, so the "getSighash" function works properly
104+
const fn = getFunctionFragment({ ...item, type: 'function', stateMutability: 'nonpayable' })
105+
if (!fn) continue
106+
const sign = fn.getSighash(item.name)
107+
if (!sign) continue
108+
if (returnDataHex === sign.replace('0x', '')) {
109+
customError = item.name
110+
const functionDesc = fn.getFunction(item.name)
111+
// decoding error parameters
112+
const decodedCustomErrorInputs = fn.decodeFunctionData(functionDesc, returnData)
113+
decodedCustomErrorInputsClean = {}
114+
let devdoc = {}
115+
// "contract" reprensents the compilation result containing the NATSPEC documentation
116+
if (contract && fn.functions && Object.keys(fn.functions).length) {
117+
const functionSignature = Object.keys(fn.functions)[0]
118+
// we check in the 'devdoc' if there's a developer documentation for this error
119+
try {
120+
devdoc = (contract.devdoc.errors && contract.devdoc.errors[functionSignature][0]) || {}
121+
} catch (e) {
122+
console.error(e.message)
123+
}
124+
// we check in the 'userdoc' if there's an user documentation for this error
125+
try {
126+
const userdoc = (contract.userdoc.errors && contract.userdoc.errors[functionSignature][0]) || {}
127+
if (userdoc && (userdoc as any).notice) customError += ' : ' + (userdoc as any).notice // we append the user doc if any
128+
} catch (e) {
129+
console.error(e.message)
130+
}
131+
}
132+
let inputIndex = 0
133+
for (const input of functionDesc.inputs) {
134+
const inputKey = input.name || inputIndex
135+
const v = decodedCustomErrorInputs[inputKey]
133136

134-
decodedCustomErrorInputsClean[inputKey] = {
135-
value: v.toString ? v.toString() : v
136-
}
137-
if (devdoc && (devdoc as any).params) {
138-
decodedCustomErrorInputsClean[input.name].documentation = (devdoc as any).params[inputKey] // we add the developer documentation for this input parameter if any
137+
decodedCustomErrorInputsClean[inputKey] = {
138+
value: v.toString ? v.toString() : v
139+
}
140+
if (devdoc && (devdoc as any).params) {
141+
decodedCustomErrorInputsClean[input.name].documentation = (devdoc as any).params[inputKey] // we add the developer documentation for this input parameter if any
142+
}
143+
inputIndex++
144+
}
145+
break
139146
}
140-
inputIndex++
141147
}
142-
break
143148
}
144149
}
145150
}

0 commit comments

Comments
 (0)