diff --git a/src/solidity-frontend/solidity_convert.cpp b/src/solidity-frontend/solidity_convert.cpp index b6e9406c16..eccf21400f 100644 --- a/src/solidity-frontend/solidity_convert.cpp +++ b/src/solidity-frontend/solidity_convert.cpp @@ -32,8 +32,7 @@ solidity_convertert::solidity_convertert( current_contractName(""), scope_map({}), tgt_func(config.options.get_option("function")), - tgt_cnt(config.options.get_option("contract")), - is_builtin_members(false) + tgt_cnt(config.options.get_option("contract")) { std::ifstream in(_contract_path); contract_contents.assign( @@ -82,14 +81,6 @@ bool solidity_convertert::convert() } assert(found_contract_def && "No contracts were found in the program."); - // pre-processing: populate built-in members into the symbol table - is_builtin_members = true; - if (convert_builtin_members()) - return true; - is_builtin_members = false; - - log_progress("Done conversion of intrinsics"); - // reasoning-based verification // populate exportedSymbolsList @@ -204,256 +195,6 @@ bool solidity_convertert::convert() return false; // 'false' indicates successful completion. } -/* - We have two approaches to handle the buitin Solidity member functions, - 1. populate the function symbol with corresponding return type and empty function body, - the symex should be implemented later - TODO: For now the added functions do not store any params. This will affect the symex - 2. convert it to a supported function in C/C++, e.g. str.concat => strcat -*/ -bool solidity_convertert::convert_builtin_members() -{ - /// special variables - // msg - populate_builtin_variables( - SolidityTemplate::msg_bs, SolidityTemplate::msg_mem); - - // tx - populate_builtin_variables(SolidityTemplate::tx_bs, SolidityTemplate::tx_mem); - - // block - populate_builtin_variables( - SolidityTemplate::block_bs, SolidityTemplate::block_mem); - - /// special functions - - // blockhash() - populate_builtin_functions("", SolidityTemplate::block_hash); - - // gasleft() - populate_builtin_functions("", SolidityTemplate::gasleft); - - // abi - populate_builtin_functions( - SolidityTemplate::abi_bs, SolidityTemplate::ai_mem); - - // byte - populate_builtin_functions( - SolidityTemplate::byte_bs, SolidityTemplate::byte_mem); - - // string - populate_builtin_functions( - SolidityTemplate::string_bs, SolidityTemplate::string_mem); - - // math - if (populate_builtin_functions( - "", SolidityTemplate::addmod, SolidityTemplate::addmod_body)) - return true; - if (populate_builtin_functions( - "", SolidityTemplate::mulmod, SolidityTemplate::mulmod_body)) - return true; - - return false; -} - -/* - Construct a symbol and move to the symbol table. - Note that this added symbol might be incomplete. -*/ -void solidity_convertert::populate_builtin_variables( - const std::string &bs, - const std::map &mems) -{ - for (const auto &item : mems) - { - const auto mem = item.first; - const auto rtn_typ = item.second; - - std::string name, id; - if (!bs.empty()) - name = bs + "_" + mem; - else - name = mem; - id = "sol:@" + name + "#"; - - locationt location_begin; - std::string debug_modulename = - get_modulename_from_path(location_begin.file().as_string()); - symbolt symbol; - - typet t; - if (rtn_typ.find("uint") != std::string::npos) - { - t = unsignedbv_typet(256); - } - else if (rtn_typ.find("bytes") != std::string::npos) - { - int byte_num; - if (rtn_typ == "bytes") - byte_num = 32; - else - byte_num = std::stoi(rtn_typ.substr(5)); - t = signedbv_typet(byte_num * 8); - } - else if (rtn_typ.find("address") != std::string::npos) - { - t = unsignedbv_typet(160); - } - else if (rtn_typ == "string") - { - size_t value_length = 128; - t = array_typet( - signed_char_type(), - constant_exprt( - integer2binary(value_length, bv_width(int_type())), - integer2string(value_length), - int_type())); - } - else - { - log_error("Unsupported Special Members."); - abort(); - } - get_default_symbol(symbol, debug_modulename, t, name, id, location_begin); - auto &sym = *move_symbol_to_context(symbol); - sym.lvalue = false; - sym.file_local = true; - symbol.mode = "C++"; - symbol.module = "esbmc_intrinsics"; - } -} - -bool solidity_convertert::populate_builtin_functions( - const std::string &bs, - const std::map &mems, - const std::string &ast_node) -{ - for (const auto &item : mems) - { - const auto mem = item.first; - const auto rtn_typ = item.second; - - std::string name, id; - if (!bs.empty()) - name = bs + "_" + mem; - else - name = mem; - id = "sol:@F@" + name + "#"; - - locationt location_begin; - std::string debug_modulename = - get_modulename_from_path(location_begin.file().as_string()); - - code_typet type; - if (rtn_typ.find("uint") != std::string::npos) - { - type.return_type() = unsignedbv_typet(256); - } - else if (rtn_typ.find("bytes") != std::string::npos) - { - int byte_num; - if (rtn_typ == "bytes") - byte_num = 32; - else - byte_num = std::stoi(rtn_typ.substr(5)); - type.return_type() = signedbv_typet(byte_num * 8); - } - else if (rtn_typ.find("address") != std::string::npos) - { - type.return_type() = unsignedbv_typet(160); - } - else if (rtn_typ == "string") - { - size_t value_length = 128; - type.return_type() = array_typet( - signed_char_type(), - constant_exprt( - integer2binary(value_length, bv_width(int_type())), - integer2string(value_length), - int_type())); - } - else - { - log_error("Unsupported Special Members."); - abort(); - } - - symbolt symbol; - get_default_symbol( - symbol, debug_modulename, type, name, id, location_begin); - - symbol.lvalue = true; - symbol.is_extern = false; - symbol.file_local = false; - symbol.mode = "C++"; - symbol.module = "esbmc_intrinsics"; - - // 10. Add symbol into the context - symbolt &added_symbol = *move_symbol_to_context(symbol); - - if (!ast_node.empty()) - { - const nlohmann::json *old_functionDecl = current_functionDecl; - const std::string old_functionName = current_functionName; - auto func_json = nlohmann::json::parse(ast_node); - current_functionDecl = &func_json; - current_functionName = name; - - SolidityGrammar::ParameterListT params = - SolidityGrammar::get_parameter_list_t(func_json["parameters"]); - if (params != SolidityGrammar::ParameterListT::EMPTY) - { - // convert parameters if the function has them - // update the typet, since typet contains parameter annotations - for (const auto &decl : func_json["parameters"]["parameters"].items()) - { - const nlohmann::json &func_param_decl = decl.value(); - - code_typet::argumentt param; - if (get_function_params(func_param_decl, param)) - return true; - - // clear the location info as it's incorrect - param.location().clear(); - param.location().set_function(name); - param.location().set_file("solidity_template"); - type.arguments().push_back(param); - } - } - added_symbol.type = type; - - assert(func_json.contains("body")); - exprt body_exprt; - if (get_block(func_json["body"], body_exprt)) - return true; - added_symbol.value = body_exprt; - - current_functionDecl = old_functionDecl; - current_functionName = old_functionName; - } - } - - return false; -} - -bool solidity_convertert::get_builtin_function_ref( - const nlohmann::json &ast_node, - exprt &new_expr) -{ - std::string name, id; - //TODO bs - name = ast_node["name"].get(); - id = "sol:@F@" + name + "#"; - - if (context.find_symbol(id) == nullptr) - return true; - - symbolt &sym = *context.find_symbol(id); - new_expr = symbol_expr(sym); - - return false; -} - bool solidity_convertert::convert_ast_nodes(const nlohmann::json &contract_def) { unsigned index = 0; @@ -1386,16 +1127,7 @@ bool solidity_convertert::get_statement( return true; } else - { - //! Assume we are handling solidity template - assert((*current_functionDecl).contains("isTemplate")); - std::string id = - (*current_functionDecl)["templateFunctionID"].get(); - if (context.find_symbol(id) == nullptr) - return true; - symbolt &sym = *context.find_symbol(id); - return_type = to_code_type(sym.type).return_type(); - } + return true; nlohmann::json literal_type = nullptr; @@ -3025,16 +2757,6 @@ bool solidity_convertert::get_decl_ref_builtin( // Add more special function names here const std::string blt_name = decl["name"].get(); - - // solidiity template - if (!(blt_name == "assert" || blt_name == "require" || blt_name == "revert" || - blt_name == "__ESBMC_assume" || blt_name == "__VERIFIER_assume")) - { - if (get_builtin_function_ref(decl, new_expr)) - return true; - return false; - } - std::string name, id; // "require" keyword is virtually identical to "assume" @@ -3353,6 +3075,15 @@ bool solidity_convertert::get_type_description( break; } + case SolidityGrammar::TypeNameT::MappingTypeName: + { + // e.g. + // mapping(uint => uint) public balances; + // ==> + // map_int_t + + break; + } default: { log_debug( @@ -3792,13 +3523,6 @@ void solidity_convertert::get_state_var_decl_name( if (!contract_name.empty()) id = "sol:@C@" + contract_name + "@" + name + "#" + i2string(ast_node["id"].get()); - else if ( - current_functionDecl && !current_functionName.empty() && is_builtin_members) - { - //!Assume is solidity_template - id = "sol:@F@" + current_functionName + "@" + name + "#" + - i2string(ast_node["id"].get()); - } else id = "sol:@" + name + "#" + i2string(ast_node["id"].get()); } @@ -3835,14 +3559,6 @@ void solidity_convertert::get_var_decl_name( id = "sol:@C@" + contract_name + "@F@" + current_functionName + "@" + name + "#" + i2string(ast_node["id"].get()); } - else if ( - current_functionDecl && !current_functionName.empty() && is_builtin_members) - { - // Assume it is a solidity template - id = "sol:@F@" + current_functionName + "@" + name + "#" + - i2string(ast_node["id"].get()); - } - else if (ast_node.contains("scope")) { // This means we are handling a local variable which is not inside a function body. @@ -4059,30 +3775,41 @@ solidity_convertert::find_decl_ref(int ref_decl_id, std::string &contract_name) abort(); } - // A "global function", which stands for the situation - // where we are handling solidity_template - // therefore, we skip the search in original src_ast_json. - if (!(current_functionDecl != nullptr && current_contractName.empty() && - is_builtin_members)) + // First, search state variable nodes + nlohmann::json &nodes = src_ast_json["nodes"]; + unsigned index = 0; + for (nlohmann::json::iterator itr = nodes.begin(); itr != nodes.end(); + ++itr, ++index) { - // First, search state variable nodes - nlohmann::json &nodes = src_ast_json["nodes"]; - unsigned index = 0; - for (nlohmann::json::iterator itr = nodes.begin(); itr != nodes.end(); - ++itr, ++index) + // check the nodes outside of the contract + // it can be referred to the data structure + // or the members inside the structure. + if ((*itr)["id"] == ref_decl_id) + return nodes.at(index); + + if ( + (*itr)["nodeType"] == "EnumDefinition" || + (*itr)["nodeType"] == "StructDefinition") { - // check the nodes outside of the contract - // it can be referred to the data structure - // or the members inside the structure. - if ((*itr)["id"] == ref_decl_id) - return nodes.at(index); + unsigned men_idx = 0; + nlohmann::json &mem_nodes = nodes.at(index)["members"]; + for (nlohmann::json::iterator mem_itr = mem_nodes.begin(); + mem_itr != mem_nodes.end(); + ++mem_itr, ++men_idx) + { + if ((*mem_itr)["id"] == ref_decl_id) + return mem_nodes.at(men_idx); + } + } + if ((*itr)["nodeType"] == "ErrorDefinition") + { if ( - (*itr)["nodeType"] == "EnumDefinition" || - (*itr)["nodeType"] == "StructDefinition") + (*itr).contains("parameters") && + ((*itr)["parameters"]).contains("parameters")) { unsigned men_idx = 0; - nlohmann::json &mem_nodes = nodes.at(index)["members"]; + nlohmann::json &mem_nodes = (*itr)["parameters"]["parameters"]; for (nlohmann::json::iterator mem_itr = mem_nodes.begin(); mem_itr != mem_nodes.end(); ++mem_itr, ++men_idx) @@ -4091,15 +3818,30 @@ solidity_convertert::find_decl_ref(int ref_decl_id, std::string &contract_name) return mem_nodes.at(men_idx); } } + } + + // check the nodes inside a contract + if ((*itr)["nodeType"] == "ContractDefinition") + { + // update the contract name first + contract_name = (*itr)["name"].get(); - if ((*itr)["nodeType"] == "ErrorDefinition") + nlohmann::json &ast_nodes = nodes.at(index)["nodes"]; + unsigned idx = 0; + for (nlohmann::json::iterator itrr = ast_nodes.begin(); + itrr != ast_nodes.end(); + ++itrr, ++idx) { + if ((*itrr)["id"] == ref_decl_id) + return ast_nodes.at(idx); + if ( - (*itr).contains("parameters") && - ((*itr)["parameters"]).contains("parameters")) + (*itrr)["nodeType"] == "EnumDefinition" || + (*itrr)["nodeType"] == "StructDefinition") { unsigned men_idx = 0; - nlohmann::json &mem_nodes = (*itr)["parameters"]["parameters"]; + nlohmann::json &mem_nodes = ast_nodes.at(idx)["members"]; + for (nlohmann::json::iterator mem_itr = mem_nodes.begin(); mem_itr != mem_nodes.end(); ++mem_itr, ++men_idx) @@ -4108,30 +3850,15 @@ solidity_convertert::find_decl_ref(int ref_decl_id, std::string &contract_name) return mem_nodes.at(men_idx); } } - } - // check the nodes inside a contract - if ((*itr)["nodeType"] == "ContractDefinition") - { - // update the contract name first - contract_name = (*itr)["name"].get(); - - nlohmann::json &ast_nodes = nodes.at(index)["nodes"]; - unsigned idx = 0; - for (nlohmann::json::iterator itrr = ast_nodes.begin(); - itrr != ast_nodes.end(); - ++itrr, ++idx) + if ((*itr)["nodeType"] == "ErrorDefinition") { - if ((*itrr)["id"] == ref_decl_id) - return ast_nodes.at(idx); - if ( - (*itrr)["nodeType"] == "EnumDefinition" || - (*itrr)["nodeType"] == "StructDefinition") + (*itr).contains("parameters") && + ((*itr)["parameters"]).contains("parameters")) { unsigned men_idx = 0; - nlohmann::json &mem_nodes = ast_nodes.at(idx)["members"]; - + nlohmann::json &mem_nodes = (*itr)["parameters"]["parameters"]; for (nlohmann::json::iterator mem_itr = mem_nodes.begin(); mem_itr != mem_nodes.end(); ++mem_itr, ++men_idx) @@ -4140,32 +3867,14 @@ solidity_convertert::find_decl_ref(int ref_decl_id, std::string &contract_name) return mem_nodes.at(men_idx); } } - - if ((*itr)["nodeType"] == "ErrorDefinition") - { - if ( - (*itr).contains("parameters") && - ((*itr)["parameters"]).contains("parameters")) - { - unsigned men_idx = 0; - nlohmann::json &mem_nodes = (*itr)["parameters"]["parameters"]; - for (nlohmann::json::iterator mem_itr = mem_nodes.begin(); - mem_itr != mem_nodes.end(); - ++mem_itr, ++men_idx) - { - if ((*mem_itr)["id"] == ref_decl_id) - return mem_nodes.at(men_idx); - } - } - } } } } - - //! otherwise, assume it is current_contractName - contract_name = current_contractName; } + //! otherwise, assume it is current_contractName + contract_name = current_contractName; + if (current_functionDecl != nullptr) { // Then search "declarations" in current function scope diff --git a/src/solidity-frontend/solidity_convert.h b/src/solidity-frontend/solidity_convert.h index 7867c4c570..ad832c90aa 100644 --- a/src/solidity-frontend/solidity_convert.h +++ b/src/solidity-frontend/solidity_convert.h @@ -26,18 +26,7 @@ class solidity_convertert bool convert(); protected: - // for builtin variables and functions bool convert_ast_nodes(const nlohmann::json &contract_def); - bool convert_builtin_members(); - void populate_builtin_variables( - const std::string &bs, - const std::map &mems); - bool populate_builtin_functions( - const std::string &bs, - const std::map &mems, - const std::string &ast_node = ""); - bool - get_builtin_function_ref(const nlohmann::json &ast_node, exprt &new_expr); // conversion functions // get decl in rule contract-body-element @@ -232,10 +221,6 @@ class solidity_convertert // --contract std::string tgt_cnt; - // flag to indicate built-in member processing - // this is used in get_(state_)var_decl_name - bool is_builtin_members; - private: bool get_elementary_type_name_uint( SolidityGrammar::ElementaryTypeNameT &type, diff --git a/src/solidity-frontend/solidity_grammar.cpp b/src/solidity-frontend/solidity_grammar.cpp index 03cf1752e7..8e99cffdb0 100644 --- a/src/solidity-frontend/solidity_grammar.cpp +++ b/src/solidity-frontend/solidity_grammar.cpp @@ -156,6 +156,10 @@ TypeNameT get_type_name_t(const nlohmann::json &type_name) { return TupleTypeName; } + else if (typeString.substr(0, 8) == "mapping(") + { + return MappingTypeName; + } else if (typeIdentifier.find("t_array$") != std::string::npos) { // Solidity's array type description is like: @@ -273,6 +277,8 @@ const char *type_name_to_str(TypeNameT type) ENUM_TO_STR(TypeConversionName) ENUM_TO_STR(EnumTypeName) ENUM_TO_STR(StructTypeName) + ENUM_TO_STR(TupleTypeName) + ENUM_TO_STR(MappingTypeName) ENUM_TO_STR(SpecialTypeName) ENUM_TO_STR(TypeNameTError) default: diff --git a/src/solidity-frontend/solidity_grammar.h b/src/solidity-frontend/solidity_grammar.h index 3bed8668c8..9a1c56e0bb 100644 --- a/src/solidity-frontend/solidity_grammar.h +++ b/src/solidity-frontend/solidity_grammar.h @@ -55,6 +55,9 @@ enum TypeNameT // struct StructTypeName, + // Mapping + MappingTypeName, + // tuple TupleTypeName, diff --git a/src/solidity-frontend/solidity_template.h b/src/solidity-frontend/solidity_template.h index 30d0758105..62c89f8b44 100644 --- a/src/solidity-frontend/solidity_template.h +++ b/src/solidity-frontend/solidity_template.h @@ -1,3 +1,7 @@ +/* + The template/library for Solidity built-in variables, function and data structure +*/ + #include #include @@ -6,505 +10,115 @@ namespace SolidityTemplate { -inline const std::string parentheis = "()"; - -/// special variables -// msg -inline std::string msg_bs = "msg"; -inline std::map msg_mem = { - {"data", "bytes"}, - {"sender", "address"}, - {"sig", "bytes4"}, - {"value", "uint"}}; - -// tx -inline std::string tx_bs = "tx"; -inline std::map tx_mem = { - {"gasprice", "uint"}, - {"origin", "address"}}; - -// block -inline std::string block_bs = "block"; -inline std::map block_mem = { - {"basefee", "uint"}, - {"chainid", "uint"}, - {"coinbase", "address"}, - {"difficulty", "uint"}, - {"gaslimit", "uint"}, - {"number", "uint"}, - {"prevrandao", "uint"}, - {"timestamp", "uint"}}; - -/// sepcial functions - -inline std::map block_hash = { - {"blockhash", "bytes32"}}; -inline std::map gasleft = {{"gasleft", "uint"}}; - -// abi -inline std::string abi_bs = "abi"; -inline std::map ai_mem = { - {"encode", "bytes"}, - {"encodePacked", "bytes"}, - {"encodeWithSelector", "bytes"}, - {"encodeWithSignature", "bytes"}, - {"encodeCall", "bytes"}}; // {"decode","tuple"}, - -// byte -inline std::string byte_bs = "byte"; -inline std::map byte_mem = { - {"concat", "bytes"}, -}; - -// string -inline std::string string_bs = "string"; -inline std::map string_mem = {{"concat", "string"}}; - -// addmod - -inline std::map addmod = {{"addmod", "uint"}}; -inline std::map mulmod = {{"mulmod", "uint"}}; -// Library wriiten in solidity +/// header & typedef -// The idea is write the function in solidity and utilize the AST-json. -// The main benifit is that we can use the uint256/int256, which are -// not currently supported in C. - -/// function body -// 1. set "stateVariable": true -// 2. add "isTemplate": true and "templateFunctionID" -// 3. make sure the Visibility is intnernal or private -/* - addmod(uint x, uint y, uint k) returns (uint) - function addmod(uint x, uint y, uint k) public returns (uint) - { - assert(k != 0); - return (x + y) % k; - } -*/ -inline const std::string addmod_body = - R"({ - "isTemplate": true, - "templateFunctionID": "sol:@F@addmod#", - "body": { - "id": 25, - "nodeType": "Block", - "src": "107:59:0", - "statements": [ - { - "expression": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 23, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "components": [ - { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 20, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 18, - "name": "x", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 3, - "src": "149:1:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "+", - "rightExpression": { - "id": 19, - "name": "y", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 5, - "src": "153:1:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "149:5:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 21, - "isConstant": false, - "isInlineArray": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "148:7:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "%", - "rightExpression": { - "id": 22, - "name": "k", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 7, - "src": "158:1:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "148:11:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "functionReturnParameters": 11, - "id": 24, - "nodeType": "Return", - "src": "141:18:0" - } - ] -}, -"functionSelector": "9796df37", -"id": 26, -"implemented": true, -"kind": "function", -"modifiers": [], -"name": "addmod", -"nameLocation": "54:6:0", -"nodeType": "FunctionDefinition", -"parameters": { - "id": 8, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 3, - "mutability": "mutable", - "name": "x", - "nameLocation": "66:1:0", - "nodeType": "VariableDeclaration", - "src": "61:6:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 2, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "61:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 5, - "mutability": "mutable", - "name": "y", - "nameLocation": "74:1:0", - "nodeType": "VariableDeclaration", - "src": "69:6:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 4, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "69:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 7, - "mutability": "mutable", - "name": "k", - "nameLocation": "82:1:0", - "nodeType": "VariableDeclaration", - "src": "77:6:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 6, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "77:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "60:24:0" -}, -"src": "45:121:0", -"stateMutability": "nonpayable", -"virtual": false, -"visibility": "private" -})"; - -inline const std::string mulmod_body = - R"({ - "isTemplate": true, - "templateFunctionID": "sol:@F@mulmod#", - "body": { - "id": 19, - "nodeType": "Block", - "src": "145:35:0", - "statements": [ - { - "expression": { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 17, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "components": [ - { - "commonType": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "id": 14, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 12, - "name": "x", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 3, - "src": "163:1:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "*", - "rightExpression": { - "id": 13, - "name": "y", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 5, - "src": "167:1:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "163:5:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 15, - "isConstant": false, - "isInlineArray": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "162:7:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "BinaryOperation", - "operator": "%", - "rightExpression": { - "id": 16, - "name": "k", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 7, - "src": "172:1:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "162:11:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "functionReturnParameters": 11, - "id": 18, - "nodeType": "Return", - "src": "155:18:0" - } - ] - }, - "id": 20, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "mulmod", - "nameLocation": "91:6:0", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 8, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 3, - "mutability": "mutable", - "name": "x", - "nameLocation": "103:1:0", - "nodeType": "VariableDeclaration", - "scope": 20, - "src": "98:6:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 2, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "98:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 5, - "mutability": "mutable", - "name": "y", - "nameLocation": "111:1:0", - "nodeType": "VariableDeclaration", - "scope": 20, - "src": "106:6:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 4, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "106:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 7, - "mutability": "mutable", - "name": "k", - "nameLocation": "119:1:0", - "nodeType": "VariableDeclaration", - "scope": 20, - "src": "114:6:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 6, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "114:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "97:24:0" - }, - "scope": 21, - "src": "82:98:0", - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "private" -})"; - -// Library written in C - -inline const std::string sol_header = R"( +const std::string sol_header = R"( #include #include #include #include )"; +/* + uint == uint256_t + bytes == uint256_t + bytes32 == uint256_t + address == address_t +*/ +const std::string sol_typedef = R"( +typedef unsigned _ExtInt(256) uint256_t; +typedef unsigned _ExtInt(160) address_t; +)"; + +/// Variables +// the value of these variables need to be set to rand afterwards + +const std::string sol_msg = R"( +uint256_t msg_data; +address_t msg_address; +__uint32_t msg_sig; +uint256_t msg_value; +)"; + +const std::string sol_tx = R"( +uint256_t tx_gasprice; +address_t tx_origin; +)"; + +const std::string sol_block = R"( +uint256_t block_basefee; +uint256_t block_chainid; +address_t block_coinbase; +uint256_t block_difficulty; +uint256_t block_gaslimit; +uint256_t block_number; +uint256_t block_prevrandao; +uint256_t block_timestamp; +)"; + +const std::string sol_vars = sol_msg + sol_tx + sol_block; + +/// functions +// if the function does not currently have an actual implement, +// leave the params empty. + +const std::string blockhash = R"( +uint256_t blockhash(); +)"; + +const std::string gasleft = R"( +uint256_t gasleft(); +)"; + +const std::string sol_abi = R"( +uint256_t abi_encode(); +uint256_t abi_encodePacked(); +uint256_t abi_encodeWithSelector(); +uint256_t abi_encodeWithSignature(); +uint256_t abi_encodeCall(); +)"; + +const std::string sol_math = R"( +uint256_t addmod(uint256_t x, uint256_t y, uint256_t k) +{ + return (x + y) % k; +} + +uint256_t mulmod(uint256_t x, uint256_t y, uint256_t k) +{ + return (x * y) % k; +} + +uint256_t keccak256(); +uint256_t sha256(); +address_t ripemd160(); +address_t ecrecover(); +)"; + +const std::string sol_string = R"( +void string_concat(char *x, char *y) +{ + strcat(x, y); +} + +size_t string_length(char *x) +{ + return strlen(x); +} +)"; + +const std::string sol_byte = R"( +void byte_concat(); +)"; + +const std::string sol_funcs = + blockhash + gasleft + sol_abi + sol_math + sol_string + sol_byte; + +/// data structure + /* https://github.com/rxi/map */ -inline const std::string sol_mapping = R"( +const std::string sol_mapping = R"( #ifndef MAP_H #define MAP_H @@ -570,8 +184,6 @@ struct map_node_t unsigned hash; void *value; map_node_t *next; - /* char key[]; */ - /* char value[]; */ }; static unsigned map_hash(const char *str) @@ -601,8 +213,6 @@ static map_node_t *map_newnode(const char *key, void *value, int vsize) static int map_bucketidx(map_base_t *m, unsigned hash) { - /* If the implementation is changed to allow a non-power-of-2 bucket count, - * the line below should be changed to use mod instead of AND */ return hash & (m->nbuckets - 1); } @@ -618,7 +228,6 @@ static int map_resize(map_base_t *m, int nbuckets) map_node_t *nodes, *node, *next; map_node_t **buckets; int i; - /* Chain all nodes together */ nodes = NULL; i = m->nbuckets; while (i--) @@ -702,14 +311,12 @@ int map_set_(map_base_t *m, const char *key, void *value, int vsize) { int n, err; map_node_t **next, *node; - /* Find & replace existing node */ next = map_getref(m, key); if (next) { memcpy((*next)->value, value, vsize); return 0; } - /* Add new node */ node = map_newnode(key, value, vsize); if (node == NULL) goto fail; @@ -775,8 +382,9 @@ const char *map_next_(map_base_t *m, map_iter_t *iter) #endif )"; -// all content plus together -inline const std::string sol_library = sol_header + sol_mapping; +// combination +const std::string sol_library = + sol_header + sol_typedef + sol_vars + sol_funcs + sol_mapping; }; // namespace SolidityTemplate