mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Implement address.transfer()
This commit is contained in:
		
							parent
							
								
									0177d964b1
								
							
						
					
					
						commit
						4264625c69
					
				| @ -2,6 +2,7 @@ | ||||
| 
 | ||||
| Features: | ||||
|  * Add ``assert(condition)``, which throws if condition is false. | ||||
|  * Introduce ``.transfer(value)`` for sending Ether. | ||||
|  * Code generator: Support ``revert()`` to abort with rolling back, but not consuming all gas. | ||||
|  * Inline assembly: Support ``revert`` (EIP140) as an opcode. | ||||
|  * Type system: Support explicit conversion of external function to address. | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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
 | ||||
|  | ||||
| @ -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), | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user