66/** IMPORT */
77const Web3 = require ( 'web3' )
88const solc = require ( 'solc' )
9- const { solcVersions } = require ( './solcVersions .js' )
9+ const { getRemoteCompiler } = require ( './remoteCompiler .js' )
1010
1111/** CONST */
1212const rexTypeError = / R e t u r n a r g u m e n t t y p e ( .* ) i s n o t i m p l i c i t l y c o n v e r t i b l e t o e x p e c t e d t y p e \( t y p e o f f i r s t r e t u r n v a r i a b l e \) / ;
13- const rexAssign = / [ ^ = ] = [ ^ = ] / ;
13+ const rexAssign = / [ ^ = ] = [ ^ = ] ; ? / ;
14+ const rexTypeDecl = / ^ ( [ \w \[ \] ] + \s ( m e m o r y | s t o r a g e ) ? \s * \w + ) ; ? $ /
1415const IGNORE_WARNINGS = [
1516 "Statement has no effect." ,
1617 "Function state mutability can be restricted to " ,
@@ -45,15 +46,19 @@ class SolidityStatement {
4546
4647 constructor ( rawCommand , scope ) {
4748 this . rawCommand = rawCommand ? rawCommand . trim ( ) : "" ;
48- this . hasNoReturnValue = ( rexAssign . test ( this . rawCommand ) ) || ( this . rawCommand . startsWith ( 'delete' ) ) || ( this . rawCommand . startsWith ( 'assembly' ) ) || ( this . rawCommand . startsWith ( 'revert' ) )
49+ this . hasNoReturnValue = ( rexAssign . test ( this . rawCommand ) )
50+ || ( this . rawCommand . startsWith ( 'delete' ) )
51+ || ( this . rawCommand . startsWith ( 'assembly' ) )
52+ || ( this . rawCommand . startsWith ( 'revert' ) )
53+ || ( rexTypeDecl . test ( this . rawCommand ) )
4954
5055 if ( scope ) {
5156 this . scope = scope
5257 } else {
5358 if ( this . rawCommand . startsWith ( 'function ' ) || this . rawCommand . startsWith ( 'modifier ' ) ) {
5459 this . scope = SCOPE . CONTRACT ;
5560 this . hasNoReturnValue = true ;
56- } else if ( this . rawCommand . startsWith ( 'mapping ' ) || this . rawCommand . startsWith ( 'event ' ) ) {
61+ } else if ( this . rawCommand . startsWith ( 'mapping ' ) || this . rawCommand . startsWith ( 'event ' ) || this . rawCommand . startsWith ( 'error ' ) ) {
5762 this . scope = SCOPE . CONTRACT ;
5863 this . hasNoReturnValue = true ;
5964 } else if ( this . rawCommand . startsWith ( 'pragma solidity ' ) ) {
@@ -111,7 +116,7 @@ class InteractiveSolidityShell {
111116 const defaults = {
112117 templateContractName : 'MainContract' ,
113118 templateFuncMain : 'main' ,
114- installedSolidityVersion : require ( '../package.json' ) . dependencies . solc . split ( "-" , 1 ) [ 0 ] ,
119+ installedSolidityVersion : null , // overridden after merging settings; never use configured value
115120 providerUrl : 'http://localhost:8545' ,
116121 autostartGanache : true ,
117122 ganacheCmd : 'ganache-cli' ,
@@ -122,6 +127,8 @@ class InteractiveSolidityShell {
122127 ...defaults , ... ( settings || { } )
123128 } ;
124129
130+ this . settings . installedSolidityVersion = require ( '../package.json' ) . dependencies . solc . split ( "-" , 1 ) [ 0 ] ;
131+
125132 this . cache = {
126133 compiler : { } /** compilerVersion:object */
127134 }
@@ -203,35 +210,38 @@ contract ${this.settings.templateContractName} {
203210
204211
205212 loadCachedCompiler ( solidityVersion ) {
206- solidityVersion = solidityVersion . startsWith ( "^" ) ? solidityVersion . substring ( 1 ) : solidityVersion ; //strip leading ^
207- /** load remote version - (maybe cache?) */
208- if ( this . cache . compiler [ solidityVersion ] ) {
209- return new Promise ( ( resolve , reject ) => {
210- return resolve ( this . cache . compiler [ solidityVersion ] ) ;
211- } ) ;
212- }
213-
214- var remoteSolidityVersion = solcVersions . find (
215- ( e ) => ! e . includes ( 'nightly' ) && e . includes ( `v${ solidityVersion } ` )
216- )
217213
214+ solidityVersion = solidityVersion . startsWith ( "^" ) ? solidityVersion . substring ( 1 ) : solidityVersion ; //strip leading ^
218215 var that = this ;
216+ /** load remote version - (maybe cache?) */
219217
220218 return new Promise ( ( resolve , reject ) => {
221- solc . loadRemoteVersion ( remoteSolidityVersion , function ( err , solcSnapshot ) {
222- that . cache . compiler [ solidityVersion ] = solcSnapshot ;
223- return resolve ( solcSnapshot )
224- } )
219+ if ( that . cache . compiler [ solidityVersion ] ) {
220+ return resolve ( that . cache . compiler [ solidityVersion ] ) ;
221+ }
222+
223+ getRemoteCompiler ( solidityVersion )
224+ . then ( remoteSolidityVersion => {
225+ solc . loadRemoteVersion ( remoteSolidityVersion , function ( err , solcSnapshot ) {
226+ that . cache . compiler [ solidityVersion ] = solcSnapshot ;
227+ return resolve ( solcSnapshot )
228+ } )
229+ } )
230+ . catch ( err => {
231+ return reject ( err )
232+ } )
225233 } ) ;
226234
227235 }
228236
229237 compile ( source , cbWarning ) {
230-
231238 let solidityVersion = getBestSolidityVersion ( source ) ;
232239
233240 return new Promise ( ( resolve , reject ) => {
234241
242+ if ( ! solidityVersion ) {
243+ return reject ( new Error ( `No valid solidity version found in source code (e.g. pragma solidity 0.8.10).` ) ) ;
244+ }
235245 this . loadCachedCompiler ( solidityVersion ) . then ( solcSelected => {
236246
237247 let input = {
@@ -263,6 +273,9 @@ contract ${this.settings.templateContractName} {
263273
264274 }
265275 return resolve ( ret ) ;
276+ } )
277+ . catch ( err => {
278+ return reject ( err ) ;
266279 } ) ;
267280
268281
@@ -296,6 +309,11 @@ contract ${this.settings.templateContractName} {
296309 } )
297310 } ) . catch ( errors => {
298311 // frownie face
312+
313+ if ( ! Array . isArray ( errors ) ) { //handle single error
314+ this . revert ( ) ;
315+ return reject ( errors ) ;
316+ }
299317 //get last typeError to detect return type:
300318 let lastTypeError = errors . slice ( ) . reverse ( ) . find ( err => err . type === "TypeError" ) ;
301319 if ( ! lastTypeError ) {
0 commit comments