diff options
Diffstat (limited to 'libsolidity/interface/ABI.cpp')
-rw-r--r-- | libsolidity/interface/ABI.cpp | 80 |
1 files changed, 62 insertions, 18 deletions
diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index 3df9d1f8..aefb34af 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -32,13 +32,14 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) for (auto it: _contractDef.interfaceFunctions()) { auto externalFunctionType = it.second->interfaceFunctionType(); + solAssert(!!externalFunctionType, ""); Json::Value method; method["type"] = "function"; method["name"] = it.second->declaration().name(); // TODO: deprecate constant in a future release - method["constant"] = it.second->stateMutability() == StateMutability::Pure || it.second->stateMutability() == StateMutability::View; - method["payable"] = it.second->isPayable(); - method["stateMutability"] = stateMutabilityToString(it.second->stateMutability()); + method["constant"] = externalFunctionType->stateMutability() == StateMutability::Pure || it.second->stateMutability() == StateMutability::View; + method["payable"] = externalFunctionType->isPayable(); + method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["inputs"] = formatTypeList( externalFunctionType->parameterNames(), externalFunctionType->parameterTypes(), @@ -53,15 +54,15 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) } if (_contractDef.constructor()) { + auto externalFunctionType = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType(); + solAssert(!!externalFunctionType, ""); Json::Value method; method["type"] = "constructor"; - auto externalFunction = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType(); - solAssert(!!externalFunction, ""); - method["payable"] = externalFunction->isPayable(); - method["stateMutability"] = stateMutabilityToString(externalFunction->stateMutability()); + method["payable"] = externalFunctionType->isPayable(); + method["stateMutability"] = stateMutabilityToString(externalFunctionType->stateMutability()); method["inputs"] = formatTypeList( - externalFunction->parameterNames(), - externalFunction->parameterTypes(), + externalFunctionType->parameterNames(), + externalFunctionType->parameterTypes(), _contractDef.isLibrary() ); abi.append(method); @@ -85,12 +86,12 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef) Json::Value params(Json::arrayValue); for (auto const& p: it->parameters()) { - solAssert(!!p->annotation().type->interfaceType(false), ""); + auto type = p->annotation().type->interfaceType(false); + solAssert(type, ""); Json::Value input; - input["name"] = p->name(); - input["type"] = p->annotation().type->interfaceType(false)->canonicalName(false); - input["indexed"] = p->isIndexed(); - params.append(input); + auto param = formatType(p->name(), *type, false); + param["indexed"] = p->isIndexed(); + params.append(param); } event["inputs"] = params; abi.append(event); @@ -110,10 +111,53 @@ Json::Value ABI::formatTypeList( for (unsigned i = 0; i < _names.size(); ++i) { solAssert(_types[i], ""); - Json::Value param; - param["name"] = _names[i]; - param["type"] = _types[i]->canonicalName(_forLibrary); - params.append(param); + params.append(formatType(_names[i], *_types[i], _forLibrary)); } return params; } + +Json::Value ABI::formatType(string const& _name, Type const& _type, bool _forLibrary) +{ + Json::Value ret; + ret["name"] = _name; + string suffix = (_forLibrary && _type.dataStoredIn(DataLocation::Storage)) ? " storage" : ""; + if (_type.isValueType() || (_forLibrary && _type.dataStoredIn(DataLocation::Storage))) + ret["type"] = _type.canonicalName() + suffix; + else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_type)) + { + if (arrayType->isByteArray()) + ret["type"] = _type.canonicalName() + suffix; + else + { + string suffix; + if (arrayType->isDynamicallySized()) + suffix = "[]"; + else + suffix = string("[") + arrayType->length().str() + "]"; + solAssert(arrayType->baseType(), ""); + Json::Value subtype = formatType("", *arrayType->baseType(), _forLibrary); + if (subtype.isMember("components")) + { + ret["type"] = subtype["type"].asString() + suffix; + ret["components"] = subtype["components"]; + } + else + ret["type"] = subtype["type"].asString() + suffix; + } + } + else if (StructType const* structType = dynamic_cast<StructType const*>(&_type)) + { + ret["type"] = "tuple"; + ret["components"] = Json::arrayValue; + for (auto const& member: structType->members(nullptr)) + { + solAssert(member.type, ""); + auto t = member.type->interfaceType(_forLibrary); + solAssert(t, ""); + ret["components"].append(formatType(member.name, *t, _forLibrary)); + } + } + else + solAssert(false, "Invalid type."); + return ret; +} |