mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #1193 from chriseth/sol_fixABIArrays
Fixed arrays in ABI.
This commit is contained in:
		
						commit
						de671024b5
					
				
							
								
								
									
										67
									
								
								Compiler.cpp
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								Compiler.cpp
									
									
									
									
									
								
							| @ -205,42 +205,49 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool | |||||||
| { | { | ||||||
| 	// We do not check the calldata size, everything is zero-padded.
 | 	// We do not check the calldata size, everything is zero-padded.
 | ||||||
| 	unsigned offset(CompilerUtils::dataStartOffset); | 	unsigned offset(CompilerUtils::dataStartOffset); | ||||||
| 	bool const c_padToWords = true; |  | ||||||
| 
 | 
 | ||||||
| 	unsigned dynamicParameterCount = 0; | 	bigint parameterHeadEnd = offset; | ||||||
| 	for (TypePointer const& type: _typeParameters) | 	for (TypePointer const& type: _typeParameters) | ||||||
| 		if (type->isDynamicallySized()) | 		parameterHeadEnd += type->isDynamicallySized() ? 32 : | ||||||
| 			dynamicParameterCount++; | 			CompilerUtils::getPaddedSize(type->getCalldataEncodedSize()); | ||||||
| 	offset += dynamicParameterCount * 32; | 	solAssert(parameterHeadEnd <= numeric_limits<unsigned>::max(), "Arguments too large."); | ||||||
| 	unsigned currentDynamicParameter = 0; | 
 | ||||||
|  | 	unsigned stackHeightOfPreviousDynamicArgument = 0; | ||||||
|  | 	ArrayType const* previousDynamicType = nullptr; | ||||||
| 	for (TypePointer const& type: _typeParameters) | 	for (TypePointer const& type: _typeParameters) | ||||||
| 		if (type->isDynamicallySized()) | 	{ | ||||||
|  | 		switch (type->getCategory()) | ||||||
| 		{ | 		{ | ||||||
| 			// value on stack: [calldata_offset] (only if we are already in dynamic mode)
 | 		case Type::Category::Array: | ||||||
| 			if (currentDynamicParameter == 0) | 			if (type->isDynamicallySized()) | ||||||
| 				// switch from static to dynamic
 | 			{ | ||||||
|  | 				// put on stack: data_offset length
 | ||||||
|  | 				unsigned newStackHeight = m_context.getStackHeight(); | ||||||
|  | 				if (previousDynamicType) | ||||||
|  | 				{ | ||||||
|  | 					// Retrieve data start offset by adding length to start offset of previous dynamic type
 | ||||||
|  | 					unsigned stackDepth = m_context.getStackHeight() - stackHeightOfPreviousDynamicArgument; | ||||||
|  | 					m_context << eth::dupInstruction(stackDepth) << eth::dupInstruction(stackDepth); | ||||||
|  | 					ArrayUtils(m_context).convertLengthToSize(*previousDynamicType); | ||||||
|  | 					m_context << u256(32) << eth::Instruction::MUL << eth::Instruction::ADD; | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 					m_context << u256(parameterHeadEnd); | ||||||
|  | 				stackHeightOfPreviousDynamicArgument = newStackHeight; | ||||||
|  | 				previousDynamicType = &dynamic_cast<ArrayType const&>(*type); | ||||||
|  | 				offset += CompilerUtils(m_context).loadFromMemory(offset, IntegerType(256), !_fromMemory); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
| 				m_context << u256(offset); | 				m_context << u256(offset); | ||||||
| 			// retrieve length
 | 				offset += CompilerUtils::getPaddedSize(type->getCalldataEncodedSize()); | ||||||
| 			CompilerUtils(m_context).loadFromMemory( | 			} | ||||||
| 				CompilerUtils::dataStartOffset + currentDynamicParameter * 32, | 			break; | ||||||
| 				IntegerType(256), !_fromMemory, c_padToWords); | 		default: | ||||||
| 			// stack: offset length
 | 			solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString()); | ||||||
| 			// add 32-byte padding to copy of length
 | 			offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, true); | ||||||
| 			m_context << u256(32) << eth::Instruction::DUP1 << u256(31) |  | ||||||
| 				<< eth::Instruction::DUP4 << eth::Instruction::ADD |  | ||||||
| 				<< eth::Instruction::DIV << eth::Instruction::MUL; |  | ||||||
| 			// stack: offset length padded_length
 |  | ||||||
| 			m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; |  | ||||||
| 			currentDynamicParameter++; |  | ||||||
| 			// stack: offset length next_calldata_offset
 |  | ||||||
| 		} | 		} | ||||||
| 		else if (currentDynamicParameter == 0) | 	} | ||||||
| 			// we can still use static load
 |  | ||||||
| 			offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, c_padToWords); |  | ||||||
| 		else |  | ||||||
| 			CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, c_padToWords); |  | ||||||
| 	if (dynamicParameterCount > 0) |  | ||||||
| 		m_context << eth::Instruction::POP; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) | void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) | ||||||
|  | |||||||
							
								
								
									
										13
									
								
								Types.cpp
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Types.cpp
									
									
									
									
									
								
							| @ -570,6 +570,15 @@ bool ArrayType::operator==(Type const& _other) const | |||||||
| 	return isDynamicallySized() || getLength()  == other.getLength(); | 	return isDynamicallySized() || getLength()  == other.getLength(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | unsigned ArrayType::getCalldataEncodedSize() const | ||||||
|  | { | ||||||
|  | 	if (isDynamicallySized()) | ||||||
|  | 		return 0; | ||||||
|  | 	bigint size = bigint(getLength()) * (isByteArray() ? 1 : getBaseType()->getCalldataEncodedSize()); | ||||||
|  | 	solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned."); | ||||||
|  | 	return unsigned(size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| u256 ArrayType::getStorageSize() const | u256 ArrayType::getStorageSize() const | ||||||
| { | { | ||||||
| 	if (isDynamicallySized()) | 	if (isDynamicallySized()) | ||||||
| @ -586,8 +595,8 @@ u256 ArrayType::getStorageSize() const | |||||||
| unsigned ArrayType::getSizeOnStack() const | unsigned ArrayType::getSizeOnStack() const | ||||||
| { | { | ||||||
| 	if (m_location == Location::CallData) | 	if (m_location == Location::CallData) | ||||||
| 		// offset, length (stack top)
 | 		// offset [length] (stack top)
 | ||||||
| 		return 2; | 		return 1 + (isDynamicallySized() ? 1 : 0); | ||||||
| 	else | 	else | ||||||
| 		// offset
 | 		// offset
 | ||||||
| 		return 1; | 		return 1; | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								Types.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Types.h
									
									
									
									
									
								
							| @ -302,6 +302,7 @@ public: | |||||||
| 	virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; | 	virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; | ||||||
| 	virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; | 	virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; | ||||||
| 	virtual bool operator==(const Type& _other) const override; | 	virtual bool operator==(const Type& _other) const override; | ||||||
|  | 	virtual unsigned getCalldataEncodedSize() const override; | ||||||
| 	virtual bool isDynamicallySized() const { return m_hasDynamicLength; } | 	virtual bool isDynamicallySized() const { return m_hasDynamicLength; } | ||||||
| 	virtual u256 getStorageSize() const override; | 	virtual u256 getStorageSize() const override; | ||||||
| 	virtual unsigned getSizeOnStack() const override; | 	virtual unsigned getSizeOnStack() const override; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user