diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/Types.cpp | 4 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 1 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 19 |
3 files changed, 19 insertions, 5 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 96b3ed17..7fccccbc 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -464,7 +464,8 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons {"call", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::Bare, true, false, true)}, {"callcode", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::BareCallCode, true, false, true)}, {"delegatecall", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Location::BareDelegateCall, true)}, - {"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Location::Send)} + {"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Location::Send)}, + {"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Location::Transfer)} }; else return MemberList::MemberMap(); @@ -2097,6 +2098,7 @@ string FunctionType::identifier() const case Location::BareDelegateCall: id += "baredelegatecall"; break; case Location::Creation: id += "creation"; break; case Location::Send: id += "send"; break; + case Location::Transfer: id += "transfer"; break; case Location::SHA3: id += "sha3"; break; case Location::Selfdestruct: id += "selfdestruct"; break; case Location::Revert: id += "revert"; break; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 3546e522..022b67c4 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -826,6 +826,7 @@ public: BareDelegateCall, ///< DELEGATECALL without function hash Creation, ///< external call using CREATE Send, ///< CALL, but without data and gas + Transfer, ///< CALL, but without data and throws on error SHA3, ///< SHA3 Selfdestruct, ///< SELFDESTRUCT Revert, ///< REVERT diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 2ed19a83..b0031513 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -616,6 +616,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) arguments.front()->accept(*this); break; case Location::Send: + case Location::Transfer: _functionCall.expression().accept(*this); // Provide the gas stipend manually at first because we may send zero ether. // Will be zeroed if we send more than zero ether. @@ -625,9 +626,12 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) *arguments.front()->annotation().type, *function.parameterTypes().front(), true ); - // gas <- gas * !value - m_context << Instruction::SWAP1 << Instruction::DUP2; - m_context << Instruction::ISZERO << Instruction::MUL << Instruction::SWAP1; + if (function.location() != Location::Transfer) + { + // gas <- gas * !value + m_context << Instruction::SWAP1 << Instruction::DUP2; + m_context << Instruction::ISZERO << Instruction::MUL << Instruction::SWAP1; + } appendExternalFunctionCall( FunctionType( TypePointers{}, @@ -644,6 +648,12 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) ), {} ); + if (function.location() == Location::Transfer) + { + // Check if zero (out of stack or not enough balance). + m_context << Instruction::ISZERO; + m_context.appendConditionalInvalid(); + } break; case Location::Selfdestruct: arguments.front()->accept(*this); @@ -960,6 +970,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) case FunctionType::Location::Bare: case FunctionType::Location::BareCallCode: case FunctionType::Location::BareDelegateCall: + case FunctionType::Location::Transfer: _memberAccess.expression().accept(*this); m_context << funType->externalIdentifier(); break; @@ -1041,7 +1052,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) ); m_context << Instruction::BALANCE; } - else if ((set<string>{"send", "call", "callcode", "delegatecall"}).count(member)) + else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) utils().convertType( *_memberAccess.expression().annotation().type, IntegerType(0, IntegerType::Modifier::Address), |