Example #1
0
void Compiler::appendInitAndConstructorCode(ContractDefinition const& _contract)
{
	// Determine the arguments that are used for the base constructors.
	std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts();
	for (ContractDefinition const* contract: bases)
	{
		if (FunctionDefinition const* constructor = contract->getConstructor())
			for (auto const& modifier: constructor->getModifiers())
			{
				auto baseContract = dynamic_cast<ContractDefinition const*>(
					&modifier->getName()->getReferencedDeclaration());
				if (baseContract)
					if (m_baseArguments.count(baseContract->getConstructor()) == 0)
						m_baseArguments[baseContract->getConstructor()] = &modifier->getArguments();
			}

		for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
		{
			ContractDefinition const* baseContract = dynamic_cast<ContractDefinition const*>(
						&base->getName()->getReferencedDeclaration());
			solAssert(baseContract, "");

			if (m_baseArguments.count(baseContract->getConstructor()) == 0)
				m_baseArguments[baseContract->getConstructor()] = &base->getArguments();
		}
	}
	// Initialization of state variables in base-to-derived order.
	for (ContractDefinition const* contract: boost::adaptors::reverse(bases))
		initializeStateVariables(*contract);

	if (FunctionDefinition const* constructor = _contract.getConstructor())
		appendConstructor(*constructor);
	else if (auto c = m_context.getNextConstructor(_contract))
		appendBaseConstructor(*c);
}
Example #2
0
void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
{
	map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.getInterfaceFunctions();
	map<FixedHash<4>, const eth::AssemblyItem> callDataUnpackerEntryPoints;

	FunctionDefinition const* fallback = _contract.getFallbackFunction();
	eth::AssemblyItem notFound = m_context.newTag();
	// shortcut messages without data if we have many functions in order to be able to receive
	// ether with constant gas
	if (interfaceFunctions.size() > 5 || fallback)
	{
		m_context << eth::Instruction::CALLDATASIZE << eth::Instruction::ISZERO;
		m_context.appendConditionalJumpTo(notFound);
	}

	// retrieve the function signature hash from the calldata
	if (!interfaceFunctions.empty())
		CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true);

	// stack now is: 1 0 <funhash>
	for (auto const& it: interfaceFunctions)
	{
		callDataUnpackerEntryPoints.insert(std::make_pair(it.first, m_context.newTag()));
		m_context << eth::dupInstruction(1) << u256(FixedHash<4>::Arith(it.first)) << eth::Instruction::EQ;
		m_context.appendConditionalJumpTo(callDataUnpackerEntryPoints.at(it.first));
	}
	m_context.appendJumpTo(notFound);

	m_context << notFound;
	if (fallback)
	{
		eth::AssemblyItem returnTag = m_context.pushNewTag();
		fallback->accept(*this);
		m_context << returnTag;
		appendReturnValuePacker(FunctionType(*fallback).getReturnParameterTypes());
	}
	else
		m_context << eth::Instruction::STOP; // function not found

	for (auto const& it: interfaceFunctions)
	{
		FunctionTypePointer const& functionType = it.second;
		solAssert(functionType->hasDeclaration(), "");
		CompilerContext::LocationSetter locationSetter(m_context, functionType->getDeclaration());
		m_context << callDataUnpackerEntryPoints.at(it.first);
		eth::AssemblyItem returnTag = m_context.pushNewTag();
		appendCalldataUnpacker(functionType->getParameterTypes());
		m_context.appendJumpTo(m_context.getFunctionEntryLabel(functionType->getDeclaration()));
		m_context << returnTag;
		appendReturnValuePacker(functionType->getReturnParameterTypes());
	}
}
Json::Value functionHashes(ContractDefinition const& _contract)
{
	Json::Value functionHashes(Json::objectValue);
	for (auto const& it: _contract.interfaceFunctions())
		functionHashes[it.second->externalSignature()] = toHex(it.first.ref());
	return functionHashes;
}
Example #4
0
bool DocStringAnalyser::visit(ContractDefinition const& _node)
{
	static const set<string> validTags = set<string>{"author", "title", "dev", "notice", "why3"};
	parseDocStrings(_node, _node.annotation(), validTags, "contracts");

	return true;
}
Example #5
0
void Compiler::initializeContext(ContractDefinition const& _contract,
								 map<ContractDefinition const*, bytes const*> const& _contracts)
{
	CompilerUtils(m_context).initialiseFreeMemoryPointer();
	m_context.setCompiledContracts(_contracts);
	m_context.setInheritanceHierarchy(_contract.getLinearizedBaseContracts());
	registerStateVariables(_contract);
	m_context.resetVisitedNodes(&_contract);
}
Example #6
0
bool ASTPrinter::visit(ContractDefinition const& _node)
{
	writeLine("ContractDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}
bool Why3Translator::visit(ContractDefinition const& _contract)
{
	if (m_seenContract)
		error(_contract, "More than one contract not supported.");
	m_seenContract = true;
	m_currentContract.contract = &_contract;
	if (_contract.isLibrary())
		error(_contract, "Libraries not supported.");

	addLine("module Contract_" + _contract.name());
	indent();
	addLine("use import int.Int");
	addLine("use import ref.Ref");
	addLine("use import map.Map");
	addLine("use import array.Array");
	addLine("use import int.ComputerDivision");
	addLine("use import mach.int.Unsigned");
	addLine("use import UInt256");
	addLine("exception Revert");
	addLine("exception Return");

	if (_contract.stateVariables().empty())
		addLine("type state = ()");
	else
	{
		addLine("type state = {");
		indent();
		m_currentContract.stateVariables = _contract.stateVariables();
		for (VariableDeclaration const* variable: m_currentContract.stateVariables)
		{
			string varType;
			try
			{
				varType = toFormalType(*variable->annotation().type);
			}
			catch (NoFormalType &err)
			{
				string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
				string typeName = typeNamePtr ? " \"" + *typeNamePtr + "\"" : "";
				fatalError(*variable, "Type" + typeName + " not supported for state variable.");
			}
			addLine("mutable _" + variable->name() + ": " + varType);
		}
		unindent();
		addLine("}");
	}

	addLine("type account = {");
	indent();
	addLine("mutable balance: uint256;");
	addLine("storage: state");
	unindent();
	addLine("}");

	addLine("val external_call (this: account): bool");
	indent();
	addLine("ensures { result = false -> this = (old this) }");
	addLine("writes { this }");
	addSourceFromDocStrings(m_currentContract.contract->annotation());
	unindent();

	if (!_contract.baseContracts().empty())
		error(*_contract.baseContracts().front(), "Inheritance not supported.");
	if (!_contract.definedStructs().empty())
		error(*_contract.definedStructs().front(), "User-defined types not supported.");
	if (!_contract.definedEnums().empty())
		error(*_contract.definedEnums().front(), "User-defined types not supported.");
	if (!_contract.events().empty())
		error(*_contract.events().front(), "Events not supported.");
	if (!_contract.functionModifiers().empty())
		error(*_contract.functionModifiers().front(), "Modifiers not supported.");

	ASTNode::listAccept(_contract.definedFunctions(), *this);

	return false;
}
Example #8
0
void Compiler::initializeStateVariables(ContractDefinition const& _contract)
{
	for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
		if (variable->getValue() && !variable->isConstant())
			ExpressionCompiler(m_context, m_optimize).appendStateVariableInitialization(*variable);
}