Merge pull request #979 from ethereum/FixGetFunction

Support resolving tuple (struct)
pull/7/head
yann300 6 years ago committed by GitHub
commit a9e03cb584
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      remix-lib/src/execution/txFormat.js
  2. 21
      remix-lib/src/execution/txHelper.js
  3. 2
      remix-lib/src/execution/txListener.js
  4. 1
      remix-lib/test/tests.js
  5. 47
      remix-lib/test/txFormat.js
  6. 147
      remix-lib/test/txHelper.js

@ -186,14 +186,12 @@ module.exports = {
callback('Error encoding arguments: ' + e)
return
}
if (!isConstructor || funArgs.length > 0) {
try {
data = helper.encodeParams(funAbi, funArgs)
dataHex = data.toString('hex')
} catch (e) {
callback('Error encoding arguments: ' + e)
return
}
try {
data = helper.encodeParams(funAbi, funArgs)
dataHex = data.toString('hex')
} catch (e) {
callback('Error encoding arguments: ' + e)
return
}
if (data.slice(0, 9) === 'undefined') {
dataHex = data.slice(9)
@ -366,7 +364,7 @@ module.exports = {
var outputTypes = []
for (i = 0; i < fnabi.outputs.length; i++) {
var type = fnabi.outputs[i].type
outputTypes.push(type === 'tuple' ? helper.makeFullTupleTypeDefinition(fnabi.outputs[i]) : type)
outputTypes.push(type.indexOf('tuple') === 0 ? helper.makeFullTupleTypeDefinition(fnabi.outputs[i]) : type)
}
if (!response.length) response = new Uint8Array(32 * fnabi.outputs.length) // ensuring the data is at least filled by 0 cause `AbiCoder` throws if there's not engouh data

@ -3,9 +3,9 @@ var ethers = require('ethers')
module.exports = {
makeFullTupleTypeDefinition: function (typeDef) {
if (typeDef && typeDef.type === 'tuple' && typeDef.components) {
if (typeDef && typeDef.type.indexOf('tuple') === 0 && typeDef.components) {
var innerTypes = typeDef.components.map((innerType) => innerType.type)
return 'tuple(' + innerTypes.join(',') + ')'
return `tuple(${innerTypes.join(',')})${this.extractSize(typeDef.type)}`
}
return typeDef.type
},
@ -15,7 +15,7 @@ module.exports = {
if (funABI.inputs && funABI.inputs.length) {
for (var i = 0; i < funABI.inputs.length; i++) {
var type = funABI.inputs[i].type
types.push(type === 'tuple' ? this.makeFullTupleTypeDefinition(funABI.inputs[i]) : type)
types.push(type.indexOf('tuple') === 0 ? this.makeFullTupleTypeDefinition(funABI.inputs[i]) : type)
if (args.length < types.length) {
args.push('')
}
@ -85,10 +85,23 @@ module.exports = {
return serialized
},
extractSize: function (type) {
var size = type.match(/([a-zA-Z0-9])(\[.*\])/)
return size ? size[2] : ''
},
getFunction: function (abi, fnName) {
for (var i = 0; i < abi.length; i++) {
var fn = abi[i]
if (fn.type === 'function' && fnName === fn.name + '(' + fn.inputs.map((value) => { return value.type }).join(',') + ')') {
if (fn.type === 'function' && fnName === fn.name + '(' + fn.inputs.map((value) => {
if (value.components) {
// we extract the size (if array) and append it later
var size = this.extractSize(value.type)
return `(${value.components.map((value) => { return value.type }).join(',')})${size}`
} else {
return value.type
}
}).join(',') + ')') {
return fn
}
}

@ -330,7 +330,7 @@ class TxListener {
var inputTypes = []
for (var i = 0; i < abi.inputs.length; i++) {
var type = abi.inputs[i].type
inputTypes.push(type === 'tuple' ? txHelper.makeFullTupleTypeDefinition(abi.inputs[i]) : type)
inputTypes.push(type.indexOf('tuple') === 0 ? txHelper.makeFullTupleTypeDefinition(abi.inputs[i]) : type)
}
var abiCoder = new ethers.utils.AbiCoder()
var decoded = abiCoder.decode(inputTypes, data)

@ -3,6 +3,7 @@ require('./eventManager.js')
require('./sourceMappingDecoder.js')
require('./util.js')
require('./txFormat.js')
require('./txHelper.js')
require('./traceManager.js')
require('./codeManager.js')

@ -184,6 +184,35 @@ tape('test abiEncoderV2', function (t) {
})
})
tape('test abiEncoderV2 array of tuple', function (t) {
t.test('(abiEncoderV2)', function (st) {
/*
{
"685e37ad": "addStructs((uint256,string))",
"e5cb65f9": "addStructs((uint256,string)[])"
}
*/
st.plan(2)
var output = compiler.compileStandardWrapper(compilerInput(abiEncoderV2ArrayOfTuple))
output = JSON.parse(output)
var contract = output.contracts['test.sol']['test']
txFormat.encodeParams('[34, "test"]', contract.abi[0], (error, encoded) => {
console.log(error)
var decoded = txFormat.decodeResponse(util.hexToIntArray(encoded.dataHex), contract.abi[0])
console.log(decoded)
st.equal(decoded[0], 'tuple(uint256,string): _strucmts 34,test')
})
txFormat.encodeParams('[[34, "test"], [123, "test2"]]', contract.abi[1], (error, encoded) => {
console.log(error)
var decoded = txFormat.decodeResponse(util.hexToIntArray(encoded.dataHex), contract.abi[1])
console.log(decoded)
st.equal(decoded[0], 'tuple(uint256,string)[]: strucmts 34,test,123,test2')
})
})
})
var uintContract = `contract uintContractTest {
uint _tp;
address _ap;
@ -251,3 +280,21 @@ contract test {
return mm;
}
}`
var abiEncoderV2ArrayOfTuple = `pragma experimental ABIEncoderV2;
contract test {
struct MyStruct {uint256 num; string _string;}
constructor (MyStruct[] _structs, string _str) {
}
function addStructs(MyStruct[] _structs) public returns (MyStruct[] strucmts) {
strucmts = _structs;
}
function addStructs(MyStruct _structs) public returns (MyStruct _strucmts) {
_strucmts = _structs;
}
}`

@ -0,0 +1,147 @@
'use strict'
var tape = require('tape')
var txHelper = require('../src/execution/txHelper')
tape('getFunction', function (st) {
st.plan(5)
var fn = txHelper.getFunction(JSON.parse(abi), 'o((address,uint256))')
st.equal(fn.name, 'o')
fn = txHelper.getFunction(JSON.parse(abi), 'i(bytes32)')
st.equal(fn.name, 'i')
fn = txHelper.getFunction(JSON.parse(abi), 'o1(string,(address,uint256),int256,int256[][3],(address,uint256)[3][])')
st.equal(fn.name, 'o1')
fn = txHelper.getConstructorInterface(JSON.parse(abi))
st.equal(fn.type, 'constructor')
fn = txHelper.getFallbackInterface(JSON.parse(abi))
st.equal(fn.type, 'fallback')
})
var abi = `[
{
"constant": false,
"inputs": [
{
"name": "_param",
"type": "bytes32"
}
],
"name": "i",
"outputs": [
{
"name": "_t",
"type": "bytes32"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_g",
"type": "string"
},
{
"components": [
{
"name": "addr",
"type": "address"
},
{
"name": "age",
"type": "uint256"
}
],
"name": "_p",
"type": "tuple"
},
{
"name": "_pg",
"type": "int256"
},
{
"name": "",
"type": "int256[][3]"
},
{
"components": [
{
"name": "addr",
"type": "address"
},
{
"name": "age",
"type": "uint256"
}
],
"name": "",
"type": "tuple[3][]"
}
],
"name": "o1",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"components": [
{
"name": "addr",
"type": "address"
},
{
"name": "age",
"type": "uint256"
}
],
"name": "_p",
"type": "tuple"
}
],
"name": "o",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"name": "_g",
"type": "bytes32"
},
{
"components": [
{
"name": "addr",
"type": "address"
},
{
"name": "age",
"type": "uint256"
}
],
"name": "u",
"type": "tuple"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"payable": false,
"stateMutability": "nonpayable",
"type": "fallback"
}
]`
Loading…
Cancel
Save