natspec for poc-9
- put natspec.js in a heredoc string (to help binary) - constructor takes no args, just sets up js vm - API: only exports Notice(transaction, abi, method, expression string) (string, error) - effort to turn natspec.js error strings to proper go errors - test errors
This commit is contained in:
		
							parent
							
								
									07955b3041
								
							
						
					
					
						commit
						97dc4edb45
					
				| @ -1,24 +1,21 @@ | |||||||
| package natspec | package natspec | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"github.com/obscuren/otto" | 	"github.com/obscuren/otto" | ||||||
| 	"io/ioutil" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NatSpec struct { | type NatSpec struct { | ||||||
| 	jsvm *otto.Otto | 	jsvm *otto.Otto | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewNATSpec(transaction string) (self *NatSpec, err error) { | // TODO: should initialise with abi and userdoc jsons
 | ||||||
|  | func NewNATSpec() (self *NatSpec, err error) { | ||||||
| 
 | 
 | ||||||
| 	self = new(NatSpec) | 	self = new(NatSpec) | ||||||
| 	self.jsvm = otto.New() | 	self.jsvm = otto.New() | ||||||
| 	code, err := ioutil.ReadFile("natspec.js") |  | ||||||
| 	if err != nil { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	_, err = self.jsvm.Run(string(code)) | 	_, err = self.jsvm.Run(natspecJS) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @ -27,39 +24,40 @@ func NewNATSpec(transaction string) (self *NatSpec, err error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	self.jsvm.Run("var transaction = " + transaction + ";") |  | ||||||
| 
 |  | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (self *NatSpec) SetDescription(desc string) (err error) { | func (self *NatSpec) Notice(transaction, abi, method, expression string) (string, error) { | ||||||
|  | 	var err error | ||||||
|  | 	if _, err = self.jsvm.Run("var transaction = " + transaction + ";"); err != nil { | ||||||
|  | 		return "", fmt.Errorf("natspec.js error setting transaction: %v", err) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	_, err = self.jsvm.Run("var expression = \"" + desc + "\";") | 	if _, err = self.jsvm.Run("var abi = " + abi + ";"); err != nil { | ||||||
| 	return | 		return "", fmt.Errorf("natspec.js error setting abi: %v", err) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| } | 	if _, err = self.jsvm.Run("var method = '" + method + "';"); err != nil { | ||||||
|  | 		return "", fmt.Errorf("natspec.js error setting method: %v", err) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| func (self *NatSpec) SetABI(abi string) (err error) { | 	if _, err = self.jsvm.Run("var expression = \"" + expression + "\";"); err != nil { | ||||||
| 
 | 		return "", fmt.Errorf("natspec.js error setting expression: %v", err) | ||||||
| 	_, err = self.jsvm.Run("var abi = " + abi + ";") | 	} | ||||||
| 	return |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (self *NatSpec) SetMethod(method string) (err error) { |  | ||||||
| 
 |  | ||||||
| 	_, err = self.jsvm.Run("var method = '" + method + "';") |  | ||||||
| 	return |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (self *NatSpec) Parse() string { |  | ||||||
| 
 | 
 | ||||||
| 	self.jsvm.Run("var call = {method: method,abi: abi,transaction: transaction};") | 	self.jsvm.Run("var call = {method: method,abi: abi,transaction: transaction};") | ||||||
| 	value, err := self.jsvm.Run("natspec.evaluateExpression(expression, call);") | 	value, err := self.jsvm.Run("natspec.evaluateExpression(expression, call);") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err.Error() | 		return "", fmt.Errorf("natspec.js error evaluating expression: %v", err) | ||||||
| 	} | 	} | ||||||
| 	return value.String() | 	evalError := "Natspec evaluation failed, wrong input params" | ||||||
|  | 	if value.String() == evalError { | ||||||
|  | 		return "", fmt.Errorf("natspec.js error evaluating expression: wrong input params in expression '%s'", expression) | ||||||
|  | 	} | ||||||
|  | 	if len(value.String()) == 0 { | ||||||
|  | 		return "", fmt.Errorf("natspec.js error evaluating expression") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return value.String(), nil | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,6 @@ | |||||||
| require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | package natspec | ||||||
|  | 
 | ||||||
|  | const natspecJS = `require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||||||
| 
 | 
 | ||||||
| },{}],2:[function(require,module,exports){ | },{}],2:[function(require,module,exports){ | ||||||
| // shim for using process in browser
 | // shim for using process in browser
 | ||||||
| @ -291,26 +293,26 @@ if (process.env.NODE_ENV !== 'build') { | |||||||
|     var BigNumber = require('bignumber.js'); // jshint ignore:line
 |     var BigNumber = require('bignumber.js'); // jshint ignore:line
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var ETH_UNITS = [  | var ETH_UNITS = [ | ||||||
|     'wei',  |     'wei', | ||||||
|     'Kwei',  |     'Kwei', | ||||||
|     'Mwei',  |     'Mwei', | ||||||
|     'Gwei',  |     'Gwei', | ||||||
|     'szabo',  |     'szabo', | ||||||
|     'finney',  |     'finney', | ||||||
|     'ether',  |     'ether', | ||||||
|     'grand',  |     'grand', | ||||||
|     'Mether',  |     'Mether', | ||||||
|     'Gether',  |     'Gether', | ||||||
|     'Tether',  |     'Tether', | ||||||
|     'Pether',  |     'Pether', | ||||||
|     'Eether',  |     'Eether', | ||||||
|     'Zether',  |     'Zether', | ||||||
|     'Yether',  |     'Yether', | ||||||
|     'Nether',  |     'Nether', | ||||||
|     'Dether',  |     'Dether', | ||||||
|     'Vether',  |     'Vether', | ||||||
|     'Uether'  |     'Uether' | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| module.exports = { | module.exports = { | ||||||
| @ -375,7 +377,7 @@ var formatInputInt = function (value) { | |||||||
|         BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE); |         BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE); | ||||||
|         value = value.round(); |         value = value.round(); | ||||||
| 
 | 
 | ||||||
|         if (value.lessThan(0))  |         if (value.lessThan(0)) | ||||||
|             value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1); |             value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1); | ||||||
|         value = value.toString(16); |         value = value.toString(16); | ||||||
|     } |     } | ||||||
| @ -404,7 +406,7 @@ var formatInputBool = function (value) { | |||||||
| /// Values are multiplied by 2^m and encoded as integers
 | /// Values are multiplied by 2^m and encoded as integers
 | ||||||
| /// @returns byte representation of real
 | /// @returns byte representation of real
 | ||||||
| var formatInputReal = function (value) { | var formatInputReal = function (value) { | ||||||
|     return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));  |     return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128))); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -436,12 +438,12 @@ var formatOutputUInt = function (value) { | |||||||
| 
 | 
 | ||||||
| /// @returns input bytes formatted to real
 | /// @returns input bytes formatted to real
 | ||||||
| var formatOutputReal = function (value) { | var formatOutputReal = function (value) { | ||||||
|     return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128));  |     return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128)); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// @returns input bytes formatted to ureal
 | /// @returns input bytes formatted to ureal
 | ||||||
| var formatOutputUReal = function (value) { | var formatOutputUReal = function (value) { | ||||||
|     return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128));  |     return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128)); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// @returns right-aligned input bytes formatted to hex
 | /// @returns right-aligned input bytes formatted to hex
 | ||||||
| @ -524,14 +526,14 @@ var namedType = function (name) { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Setups input formatters for solidity types
 | /// Setups input formatters for solidity types
 | ||||||
| /// @returns an array of input formatters 
 | /// @returns an array of input formatters
 | ||||||
| var inputTypes = function () { | var inputTypes = function () { | ||||||
|      | 
 | ||||||
|     return [ |     return [ | ||||||
|         { type: prefixedType('uint'), format: f.formatInputInt }, |         { type: prefixedType('uint'), format: f.formatInputInt }, | ||||||
|         { type: prefixedType('int'), format: f.formatInputInt }, |         { type: prefixedType('int'), format: f.formatInputInt }, | ||||||
|         { type: prefixedType('hash'), format: f.formatInputInt }, |         { type: prefixedType('hash'), format: f.formatInputInt }, | ||||||
|         { type: prefixedType('string'), format: f.formatInputString },  |         { type: prefixedType('string'), format: f.formatInputString }, | ||||||
|         { type: prefixedType('real'), format: f.formatInputReal }, |         { type: prefixedType('real'), format: f.formatInputReal }, | ||||||
|         { type: prefixedType('ureal'), format: f.formatInputReal }, |         { type: prefixedType('ureal'), format: f.formatInputReal }, | ||||||
|         { type: namedType('address'), format: f.formatInputInt }, |         { type: namedType('address'), format: f.formatInputInt }, | ||||||
| @ -620,7 +622,7 @@ var toAscii = function(hex) { | |||||||
| 
 | 
 | ||||||
|     return str; |     return str; | ||||||
| }; | }; | ||||||
|      | 
 | ||||||
| var toHex = function(str) { | var toHex = function(str) { | ||||||
|     var hex = ""; |     var hex = ""; | ||||||
|     for(var i = 0; i < str.length; i++) { |     for(var i = 0; i < str.length; i++) { | ||||||
| @ -642,7 +644,7 @@ var fromAscii = function(str, pad) { | |||||||
| 
 | 
 | ||||||
| /// @returns display name for function/event eg. multiply(uint256) -> multiply
 | /// @returns display name for function/event eg. multiply(uint256) -> multiply
 | ||||||
| var extractDisplayName = function (name) { | var extractDisplayName = function (name) { | ||||||
|     var length = name.indexOf('(');  |     var length = name.indexOf('('); | ||||||
|     return length !== -1 ? name.substr(0, length) : name; |     return length !== -1 ? name.substr(0, length) : name; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -657,8 +659,8 @@ var extractTypeName = function (name) { | |||||||
| /// @returns abi array with filtered objects of type 'function'
 | /// @returns abi array with filtered objects of type 'function'
 | ||||||
| var filterFunctions = function (json) { | var filterFunctions = function (json) { | ||||||
|     return json.filter(function (current) { |     return json.filter(function (current) { | ||||||
|         return current.type === 'function';  |         return current.type === 'function'; | ||||||
|     });  |     }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Filters all events form input abi
 | /// Filters all events form input abi
 | ||||||
| @ -3404,7 +3406,7 @@ module.exports = { | |||||||
|  * @date 2015 |  * @date 2015 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| var abi = require('./node_modules/ethereum.js/lib/abi.js');  | var abi = require('./node_modules/ethereum.js/lib/abi.js'); | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This object should be used to evaluate natspec expression |  * This object should be used to evaluate natspec expression | ||||||
| @ -3418,7 +3420,7 @@ var natspec = (function () { | |||||||
|             context[key] = obj[key]; |             context[key] = obj[key]; | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|      | 
 | ||||||
|     /// generate codes, which will be evaluated
 |     /// generate codes, which will be evaluated
 | ||||||
|     var generateCode = function (obj) { |     var generateCode = function (obj) { | ||||||
|         return Object.keys(obj).reduce(function (acc, key) { |         return Object.keys(obj).reduce(function (acc, key) { | ||||||
| @ -3440,20 +3442,20 @@ var natspec = (function () { | |||||||
|     /// @returns hashmap with all contract's method input variables
 |     /// @returns hashmap with all contract's method input variables
 | ||||||
|     var getMethodInputParams = function (method, transaction) { |     var getMethodInputParams = function (method, transaction) { | ||||||
|         // do it with output formatter (cause we have to decode)
 |         // do it with output formatter (cause we have to decode)
 | ||||||
|         var params = abi.formatOutput(method.inputs, '0x' + transaction.params[0].data.slice(10));  |         var params = abi.formatOutput(method.inputs, '0x' + transaction.params[0].data.slice(10)); | ||||||
| 
 | 
 | ||||||
|         return method.inputs.reduce(function (acc, current, index) { |         return method.inputs.reduce(function (acc, current, index) { | ||||||
|             acc[current.name] = params[index]; |             acc[current.name] = params[index]; | ||||||
|             return acc; |             return acc; | ||||||
|         }, {}); |         }, {}); | ||||||
|     }; |     }; | ||||||
|      | 
 | ||||||
|     /// Should be called to evaluate expression
 |     /// Should be called to evaluate expression
 | ||||||
|     var mapExpressionsToEvaluate = function (expression, cb) { |     var mapExpressionsToEvaluate = function (expression, cb) { | ||||||
|         var evaluatedExpression = ""; |         var evaluatedExpression = ""; | ||||||
| 
 | 
 | ||||||
|         // match everything in `` quotes
 |         // match everything in backtick
 | ||||||
|         var pattern = /\`(?:\\.|[^`\\])*\`/gim |         var pattern = /\` + "`" + `(?:\\.|[^` + "`" + `\\])*\` + "`" + `/gim | ||||||
|         var match; |         var match; | ||||||
|         var lastIndex = 0; |         var lastIndex = 0; | ||||||
|         while ((match = pattern.exec(expression)) !== null) { |         while ((match = pattern.exec(expression)) !== null) { | ||||||
| @ -3464,9 +3466,9 @@ var natspec = (function () { | |||||||
|             evaluatedExpression += evaluatedPart; |             evaluatedExpression += evaluatedPart; | ||||||
|             lastIndex = pattern.lastIndex; |             lastIndex = pattern.lastIndex; | ||||||
|         } |         } | ||||||
|          | 
 | ||||||
|         evaluatedExpression += expression.slice(lastIndex); |         evaluatedExpression += expression.slice(lastIndex); | ||||||
|      | 
 | ||||||
|         return evaluatedExpression; |         return evaluatedExpression; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @ -3478,11 +3480,11 @@ var natspec = (function () { | |||||||
|     var evaluateExpression = function (expression, call) { |     var evaluateExpression = function (expression, call) { | ||||||
|         //var self = this;
 |         //var self = this;
 | ||||||
|         var context = {}; |         var context = {}; | ||||||
|          | 
 | ||||||
|         if (!!call) { |         if (!!call) { | ||||||
|             try { |             try { | ||||||
|                 var method = getMethodWithName(call.abi, call.method); |                 var method = getMethodWithName(call.abi, call.method); | ||||||
|                 var params = getMethodInputParams(method, call.transaction);  |                 var params = getMethodInputParams(method, call.transaction); | ||||||
|                 copyToContext(params, context); |                 copyToContext(params, context); | ||||||
|             } |             } | ||||||
|             catch (err) { |             catch (err) { | ||||||
| @ -3498,7 +3500,7 @@ var natspec = (function () { | |||||||
|                 return fn(context).toString(); |                 return fn(context).toString(); | ||||||
|             } |             } | ||||||
|             catch (err) { |             catch (err) { | ||||||
|                 return 'undefined';  |                 return 'undefined'; | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -3511,7 +3513,8 @@ var natspec = (function () { | |||||||
| 
 | 
 | ||||||
| })(); | })(); | ||||||
| 
 | 
 | ||||||
| module.exports = natspec;  | module.exports = natspec; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| },{"./node_modules/ethereum.js/lib/abi.js":3}]},{},[]); | },{"./node_modules/ethereum.js/lib/abi.js":3}]},{},[]); | ||||||
|  | ` | ||||||
| @ -6,41 +6,48 @@ import ( | |||||||
| 
 | 
 | ||||||
| func TestNotice(t *testing.T) { | func TestNotice(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	ns, err := NewNATSpec(` | 	tx := ` | ||||||
| 	{ | 	{ | ||||||
|             "jsonrpc": "2.0", |     "jsonrpc": "2.0", | ||||||
|             "method": "eth_call", |     "method": "eth_call", | ||||||
|             "params": [{ |     "params": [{ | ||||||
|                 "to": "0x8521742d3f456bd237e312d6e30724960f72517a", |         "to": "0x8521742d3f456bd237e312d6e30724960f72517a", | ||||||
|                 "data": "0xc6888fa1000000000000000000000000000000000000000000000000000000000000007a" |         "data": "0xc6888fa1000000000000000000000000000000000000000000000000000000000000007a" | ||||||
|             }], |     }], | ||||||
|             "id": 6 |     "id": 6 | ||||||
|         } |   } | ||||||
| 	`) | 	` | ||||||
| 
 | 
 | ||||||
|  | 	abi := ` | ||||||
|  | 	[{ | ||||||
|  |     "name": "multiply", | ||||||
|  |     "constant": false, | ||||||
|  |     "type": "function", | ||||||
|  |     "inputs": [{ | ||||||
|  |       "name": "a", | ||||||
|  |       "type": "uint256" | ||||||
|  |     }], | ||||||
|  |     "outputs": [{ | ||||||
|  |       "name": "d", | ||||||
|  |       "type": "uint256" | ||||||
|  |     }] | ||||||
|  |   }] | ||||||
|  | 	` | ||||||
|  | 
 | ||||||
|  | 	desc := "Will multiply `a` by 7 and return `a * 7`." | ||||||
|  | 
 | ||||||
|  | 	method := "multiply" | ||||||
|  | 
 | ||||||
|  | 	ns, err := NewNATSpec() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("NewNATSpec error %v", err) | 		t.Errorf("NewNATSpec error %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ns.SetABI(` | 	notice, err := ns.Notice(tx, abi, method, desc) | ||||||
| 	[{ |  | ||||||
|             "name": "multiply", |  | ||||||
|             "constant": false, |  | ||||||
|             "type": "function", |  | ||||||
|             "inputs": [{ |  | ||||||
|                 "name": "a", |  | ||||||
|                 "type": "uint256" |  | ||||||
|             }], |  | ||||||
|             "outputs": [{ |  | ||||||
|                 "name": "d", |  | ||||||
|                 "type": "uint256" |  | ||||||
|             }] |  | ||||||
|         }] |  | ||||||
| 	`) |  | ||||||
| 	ns.SetDescription("Will multiply `a` by 7 and return `a * 7`.") |  | ||||||
| 	ns.SetMethod("multiply") |  | ||||||
| 
 | 
 | ||||||
| 	notice := ns.Parse() | 	if err != nil { | ||||||
|  | 		t.Errorf("expected no error got %v", err) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	expected := "Will multiply 122 by 7 and return 854." | 	expected := "Will multiply 122 by 7 and return 854." | ||||||
| 	if notice != expected { | 	if notice != expected { | ||||||
| @ -48,4 +55,42 @@ func TestNotice(t *testing.T) { | |||||||
| 	} else { | 	} else { | ||||||
| 		t.Logf("returned notice \"%v\"", notice) | 		t.Logf("returned notice \"%v\"", notice) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	notice, err = ns.Notice(tx, abi, method, "Will multiply 122 by \"7\" and return 854.") | ||||||
|  | 
 | ||||||
|  | 	expected = "natspec.js error setting expression: (anonymous): Line 1:41 Unexpected number" | ||||||
|  | 
 | ||||||
|  | 	if err == nil { | ||||||
|  | 		t.Errorf("expected error, got nothing (notice: '%v')", err, notice) | ||||||
|  | 	} else { | ||||||
|  | 		if err.Error() != expected { | ||||||
|  | 			t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// badDesc := "Will multiply `e` by 7 and return `a * 7`."
 | ||||||
|  | 	// notice, err = ns.Notice(tx, abi, method, badDesc)
 | ||||||
|  | 
 | ||||||
|  | 	// expected = "natspec.js error evaluating expression: wrong input param in expression ''"
 | ||||||
|  | 
 | ||||||
|  | 	// if err == nil {
 | ||||||
|  | 	// 	t.Errorf("expected error, got nothing (notice: '%v')", notice)
 | ||||||
|  | 	// } else {
 | ||||||
|  | 	// 	if err.Error() != expected {
 | ||||||
|  | 	// 		t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
 | ||||||
|  | 	// 	}
 | ||||||
|  | 	// }
 | ||||||
|  | 
 | ||||||
|  | 	notice, err = ns.Notice(tx, abi, "missing_method", desc) | ||||||
|  | 
 | ||||||
|  | 	expected = "natspec.js error evaluating expression: wrong input params in expression 'Will multiply `a` by 7 and return `a * 7`.'" | ||||||
|  | 
 | ||||||
|  | 	if err == nil { | ||||||
|  | 		t.Errorf("expected error, got nothing (notice: '%v')", notice) | ||||||
|  | 	} else { | ||||||
|  | 		if err.Error() != expected { | ||||||
|  | 			t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user