mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
commit
af6afb0415
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
|||||||
|
.commit_hash.txt
|
||||||
|
.prerelease.txt
|
||||||
|
|
||||||
# Compiled Object files
|
# Compiled Object files
|
||||||
*.slo
|
*.slo
|
||||||
*.lo
|
*.lo
|
||||||
|
@ -8,7 +8,7 @@ include(EthPolicy)
|
|||||||
eth_policy()
|
eth_policy()
|
||||||
|
|
||||||
# project name and version should be set after cmake_policy CMP0048
|
# project name and version should be set after cmake_policy CMP0048
|
||||||
set(PROJECT_VERSION "0.4.1")
|
set(PROJECT_VERSION "0.4.2")
|
||||||
project(solidity VERSION ${PROJECT_VERSION})
|
project(solidity VERSION ${PROJECT_VERSION})
|
||||||
|
|
||||||
# Let's find our dependencies
|
# Let's find our dependencies
|
||||||
|
13
Changelog.md
13
Changelog.md
@ -1,3 +1,16 @@
|
|||||||
|
### 0.4.2 (2016-09-17)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
|
||||||
|
* Code Generator: Fix library functions being called from payable functions.
|
||||||
|
* Type Checker: Fixed a crash about invalid array types.
|
||||||
|
* Code Generator: Fixed a call gas bug that became visible after
|
||||||
|
version 0.4.0 for calls where the output is larger than the input.
|
||||||
|
|
||||||
|
### 0.4.1 (2016-09-09)
|
||||||
|
|
||||||
|
* Build System: Fixes to allow library compilation.
|
||||||
|
|
||||||
### 0.4.0 (2016-09-08)
|
### 0.4.0 (2016-09-08)
|
||||||
|
|
||||||
This release deliberately breaks backwards compatibility mostly to
|
This release deliberately breaks backwards compatibility mostly to
|
||||||
|
@ -26,6 +26,7 @@ if (EXISTS ${ETH_SOURCE_DIR}/prerelease.txt)
|
|||||||
string(STRIP "${SOL_VERSION_PRERELEASE}" SOL_VERSION_PRERELEASE)
|
string(STRIP "${SOL_VERSION_PRERELEASE}" SOL_VERSION_PRERELEASE)
|
||||||
else()
|
else()
|
||||||
string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC)
|
string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC)
|
||||||
|
string(REPLACE .0 . SOL_VERSION_PRERELEASE "${SOL_VERSION_PRERELEASE}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt)
|
if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt)
|
||||||
@ -33,7 +34,7 @@ if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt)
|
|||||||
string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH)
|
string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH)
|
||||||
else()
|
else()
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse HEAD
|
COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse --short=8 HEAD
|
||||||
OUTPUT_VARIABLE SOL_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET
|
OUTPUT_VARIABLE SOL_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET
|
||||||
)
|
)
|
||||||
execute_process(
|
execute_process(
|
||||||
@ -47,14 +48,17 @@ if (SOL_COMMIT_HASH)
|
|||||||
string(SUBSTRING ${SOL_COMMIT_HASH} 0 8 SOL_COMMIT_HASH)
|
string(SUBSTRING ${SOL_COMMIT_HASH} 0 8 SOL_COMMIT_HASH)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES)
|
|
||||||
set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT SOL_COMMIT_HASH)
|
if (NOT SOL_COMMIT_HASH)
|
||||||
message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or "
|
message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or "
|
||||||
"supply a file called commit_hash.txt")
|
"supply a file called commit_hash.txt")
|
||||||
endif()
|
endif()
|
||||||
|
if (NOT SOL_COMMIT_HASH MATCHES [a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9])
|
||||||
|
message(FATAL_ERROR "Malformed commit hash \"${SOL_COMMIT_HASH}\". It has to consist of exactly 8 hex digits.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES)
|
||||||
|
set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}")
|
set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}")
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ copyright = '2016, Ethereum'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.2.0'
|
version = '0.4.1'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.2.0'
|
release = '0.4.1-develop'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
@ -6,6 +6,15 @@
|
|||||||
Installing Solidity
|
Installing Solidity
|
||||||
###################
|
###################
|
||||||
|
|
||||||
|
Versioning
|
||||||
|
==========
|
||||||
|
|
||||||
|
Solidity versions follow `semantic versioning <https://semver.org>` and in addition to
|
||||||
|
releases, **nightly development builds** are also made available. The nightly builds
|
||||||
|
are not guaranteed to be working and despite best efforts they might contain undocumented
|
||||||
|
and/or broken changes. We recommend to use the latest release. Package installers below
|
||||||
|
will use the latest release.
|
||||||
|
|
||||||
Browser-Solidity
|
Browser-Solidity
|
||||||
================
|
================
|
||||||
|
|
||||||
@ -186,3 +195,20 @@ Alternatively, you can build for Windows on the command-line, like so:
|
|||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
cmake --build . --config RelWithDebInfo
|
cmake --build . --config RelWithDebInfo
|
||||||
|
|
||||||
|
Important information about versioning
|
||||||
|
======================================
|
||||||
|
|
||||||
|
After a release is made, the patch version level is bumped, because we assume that only
|
||||||
|
patch level changes follow. When changes are merged, the version should be bumped according
|
||||||
|
to semver and the severity of the change. Finally, a release is always made with the version
|
||||||
|
of the current nightly build, but without the ``prerelease`` specifier.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- 0) the 0.4.0 release is made
|
||||||
|
- 1) nightly build has a version of 0.4.1 from now on
|
||||||
|
- 2) non-breaking changes are introduced - no change in version
|
||||||
|
- 3) a breaking change is introduced - version is bumped to 0.5.0
|
||||||
|
- 4) the 0.5.0 release is made
|
||||||
|
|
||||||
|
This behaviour works well with the version pragma.
|
||||||
|
@ -73,7 +73,7 @@ inline bool assertEqualAux(A const& _a, B const& _b, char const* _aStr, char con
|
|||||||
/// Use it as assertThrow(1 == 1, ExceptionType, "Mathematics is wrong.");
|
/// Use it as assertThrow(1 == 1, ExceptionType, "Mathematics is wrong.");
|
||||||
/// Do NOT supply an exception object as the second parameter.
|
/// Do NOT supply an exception object as the second parameter.
|
||||||
#define assertThrow(_condition, _ExceptionType, _description) \
|
#define assertThrow(_condition, _ExceptionType, _description) \
|
||||||
::dev::assertThrowAux<_ExceptionType>(_condition, _description, __LINE__, __FILE__, ETH_FUNC)
|
::dev::assertThrowAux<_ExceptionType>(!!(_condition), _description, __LINE__, __FILE__, ETH_FUNC)
|
||||||
|
|
||||||
using errinfo_comment = boost::error_info<struct tag_comment, std::string>;
|
using errinfo_comment = boost::error_info<struct tag_comment, std::string>;
|
||||||
|
|
||||||
@ -96,16 +96,4 @@ inline void assertThrowAux(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _ExceptionType>
|
|
||||||
inline void assertThrowAux(
|
|
||||||
void const* _pointer,
|
|
||||||
::std::string const& _errorDescription,
|
|
||||||
unsigned _line,
|
|
||||||
char const* _file,
|
|
||||||
char const* _function
|
|
||||||
)
|
|
||||||
{
|
|
||||||
assertThrowAux<_ExceptionType>(_pointer != nullptr, _errorDescription, _line, _file, _function);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1438,7 +1438,7 @@ bool TypeChecker::visit(IndexAccess const& _access)
|
|||||||
length->literalValue(nullptr)
|
length->literalValue(nullptr)
|
||||||
));
|
));
|
||||||
else
|
else
|
||||||
typeError(index->location(), "Integer constant expected.");
|
fatalTypeError(index->location(), "Integer constant expected.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,9 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
|||||||
CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration());
|
CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration());
|
||||||
|
|
||||||
m_context << callDataUnpackerEntryPoints.at(it.first);
|
m_context << callDataUnpackerEntryPoints.at(it.first);
|
||||||
if (!functionType->isPayable())
|
// We have to allow this for libraries, because value of the previous
|
||||||
|
// call is still visible in the delegatecall.
|
||||||
|
if (!functionType->isPayable() && !_contract.isLibrary())
|
||||||
{
|
{
|
||||||
// Throw if function is not payable but call contained ether.
|
// Throw if function is not payable but call contained ether.
|
||||||
m_context << Instruction::CALLVALUE;
|
m_context << Instruction::CALLVALUE;
|
||||||
|
@ -1476,6 +1476,18 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
|||||||
utils().storeFreeMemoryPointer();
|
utils().storeFreeMemoryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Touch the end of the output area so that we do not pay for memory resize during the call
|
||||||
|
// (which we would have to subtract from the gas left)
|
||||||
|
// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
|
||||||
|
// would remove that, so we use MSTORE here.
|
||||||
|
if (!_functionType.gasSet() && retSize > 0)
|
||||||
|
{
|
||||||
|
m_context << u256(0);
|
||||||
|
utils().fetchFreeMemoryPointer();
|
||||||
|
// This touches too much, but that way we save some rounding arithmetics
|
||||||
|
m_context << u256(retSize) << Instruction::ADD << Instruction::MSTORE;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy function identifier to memory.
|
// Copy function identifier to memory.
|
||||||
utils().fetchFreeMemoryPointer();
|
utils().fetchFreeMemoryPointer();
|
||||||
if (!_functionType.isBareCall() || manualFunctionId)
|
if (!_functionType.isBareCall() || manualFunctionId)
|
||||||
@ -1551,10 +1563,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
|||||||
gasNeededByCaller += eth::GasCosts::callValueTransferGas;
|
gasNeededByCaller += eth::GasCosts::callValueTransferGas;
|
||||||
if (!isCallCode && !isDelegateCall && !existenceChecked)
|
if (!isCallCode && !isDelegateCall && !existenceChecked)
|
||||||
gasNeededByCaller += eth::GasCosts::callNewAccountGas; // we never know
|
gasNeededByCaller += eth::GasCosts::callNewAccountGas; // we never know
|
||||||
m_context <<
|
m_context << gasNeededByCaller << Instruction::GAS << Instruction::SUB;
|
||||||
gasNeededByCaller <<
|
|
||||||
Instruction::GAS <<
|
|
||||||
Instruction::SUB;
|
|
||||||
}
|
}
|
||||||
if (isDelegateCall)
|
if (isDelegateCall)
|
||||||
m_context << Instruction::DELEGATECALL;
|
m_context << Instruction::DELEGATECALL;
|
||||||
|
@ -36,6 +36,10 @@ bool Why3Translator::process(SourceUnit const& _source)
|
|||||||
appendPreface();
|
appendPreface();
|
||||||
_source.accept(*this);
|
_source.accept(*this);
|
||||||
}
|
}
|
||||||
|
catch (NoFormalType&)
|
||||||
|
{
|
||||||
|
solAssert(false, "There is a call to toFormalType() that does not catch NoFormalType exceptions.");
|
||||||
|
}
|
||||||
catch (FatalError& /*_e*/)
|
catch (FatalError& /*_e*/)
|
||||||
{
|
{
|
||||||
solAssert(m_errorOccured, "");
|
solAssert(m_errorOccured, "");
|
||||||
@ -77,14 +81,30 @@ string Why3Translator::toFormalType(Type const& _type) const
|
|||||||
return "uint256";
|
return "uint256";
|
||||||
}
|
}
|
||||||
else if (auto type = dynamic_cast<ArrayType const*>(&_type))
|
else if (auto type = dynamic_cast<ArrayType const*>(&_type))
|
||||||
|
{
|
||||||
if (!type->isByteArray() && type->isDynamicallySized() && type->dataStoredIn(DataLocation::Memory))
|
if (!type->isByteArray() && type->isDynamicallySized() && type->dataStoredIn(DataLocation::Memory))
|
||||||
{
|
{
|
||||||
|
// Not catching NoFormalType exception. Let the caller deal with it.
|
||||||
string base = toFormalType(*type->baseType());
|
string base = toFormalType(*type->baseType());
|
||||||
if (!base.empty())
|
return "array " + base;
|
||||||
return "array " + base;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (auto mappingType = dynamic_cast<MappingType const*>(&_type))
|
||||||
|
{
|
||||||
|
solAssert(mappingType->keyType(), "A mappingType misses a keyType.");
|
||||||
|
if (dynamic_cast<IntegerType const*>(&*mappingType->keyType()))
|
||||||
|
{
|
||||||
|
//@TODO Use the information from the key type and specify the length of the array as an invariant.
|
||||||
|
// Also the constructor need to specify the length of the array.
|
||||||
|
solAssert(mappingType->valueType(), "A mappingType misses a valueType.");
|
||||||
|
// Not catching NoFormalType exception. Let the caller deal with it.
|
||||||
|
string valueTypeFormal = toFormalType(*mappingType->valueType());
|
||||||
|
return "array " + valueTypeFormal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
BOOST_THROW_EXCEPTION(NoFormalType()
|
||||||
|
<< errinfo_noFormalTypeFrom(_type.toString(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Why3Translator::addLine(string const& _line)
|
void Why3Translator::addLine(string const& _line)
|
||||||
@ -142,9 +162,17 @@ bool Why3Translator::visit(ContractDefinition const& _contract)
|
|||||||
m_currentContract.stateVariables = _contract.stateVariables();
|
m_currentContract.stateVariables = _contract.stateVariables();
|
||||||
for (VariableDeclaration const* variable: m_currentContract.stateVariables)
|
for (VariableDeclaration const* variable: m_currentContract.stateVariables)
|
||||||
{
|
{
|
||||||
string varType = toFormalType(*variable->annotation().type);
|
string varType;
|
||||||
if (varType.empty())
|
try
|
||||||
fatalError(*variable, "Type not supported for state variable.");
|
{
|
||||||
|
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);
|
addLine("mutable _" + variable->name() + ": " + varType);
|
||||||
}
|
}
|
||||||
unindent();
|
unindent();
|
||||||
@ -218,9 +246,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
|
|||||||
add(" (this: account)");
|
add(" (this: account)");
|
||||||
for (auto const& param: _function.parameters())
|
for (auto const& param: _function.parameters())
|
||||||
{
|
{
|
||||||
string paramType = toFormalType(*param->annotation().type);
|
string paramType;
|
||||||
if (paramType.empty())
|
try
|
||||||
error(*param, "Parameter type not supported.");
|
{
|
||||||
|
paramType = toFormalType(*param->annotation().type);
|
||||||
|
}
|
||||||
|
catch (NoFormalType &err)
|
||||||
|
{
|
||||||
|
string const* typeName = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
|
||||||
|
error(*param, "Parameter type \"" + (typeName ? *typeName : "") + "\" not supported.");
|
||||||
|
}
|
||||||
if (param->name().empty())
|
if (param->name().empty())
|
||||||
error(*param, "Anonymous function parameters not supported.");
|
error(*param, "Anonymous function parameters not supported.");
|
||||||
add(" (arg_" + param->name() + ": " + paramType + ")");
|
add(" (arg_" + param->name() + ": " + paramType + ")");
|
||||||
@ -232,9 +267,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
|
|||||||
string retString = "(";
|
string retString = "(";
|
||||||
for (auto const& retParam: _function.returnParameters())
|
for (auto const& retParam: _function.returnParameters())
|
||||||
{
|
{
|
||||||
string paramType = toFormalType(*retParam->annotation().type);
|
string paramType;
|
||||||
if (paramType.empty())
|
try
|
||||||
error(*retParam, "Parameter type not supported.");
|
{
|
||||||
|
paramType = toFormalType(*retParam->annotation().type);
|
||||||
|
}
|
||||||
|
catch (NoFormalType &err)
|
||||||
|
{
|
||||||
|
string const* typeName = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
|
||||||
|
error(*retParam, "Parameter type " + (typeName ? *typeName : "") + " not supported.");
|
||||||
|
}
|
||||||
if (retString.size() != 1)
|
if (retString.size() != 1)
|
||||||
retString += ", ";
|
retString += ", ";
|
||||||
retString += paramType;
|
retString += paramType;
|
||||||
@ -264,14 +306,32 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
|
|||||||
{
|
{
|
||||||
if (variable->name().empty())
|
if (variable->name().empty())
|
||||||
error(*variable, "Unnamed return variables not yet supported.");
|
error(*variable, "Unnamed return variables not yet supported.");
|
||||||
string varType = toFormalType(*variable->annotation().type);
|
string varType;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
varType = toFormalType(*variable->annotation().type);
|
||||||
|
}
|
||||||
|
catch (NoFormalType &err)
|
||||||
|
{
|
||||||
|
string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
|
||||||
|
error(*variable, "Type " + (typeNamePtr ? *typeNamePtr : "") + "in return parameter not yet supported.");
|
||||||
|
}
|
||||||
addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in");
|
addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in");
|
||||||
}
|
}
|
||||||
for (VariableDeclaration const* variable: _function.localVariables())
|
for (VariableDeclaration const* variable: _function.localVariables())
|
||||||
{
|
{
|
||||||
if (variable->name().empty())
|
if (variable->name().empty())
|
||||||
error(*variable, "Unnamed variables not yet supported.");
|
error(*variable, "Unnamed variables not yet supported.");
|
||||||
string varType = toFormalType(*variable->annotation().type);
|
string varType;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
varType = toFormalType(*variable->annotation().type);
|
||||||
|
}
|
||||||
|
catch (NoFormalType &err)
|
||||||
|
{
|
||||||
|
string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
|
||||||
|
error(*variable, "Type " + (typeNamePtr ? *typeNamePtr : "") + "in variable declaration not yet supported.");
|
||||||
|
}
|
||||||
addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in");
|
addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in");
|
||||||
}
|
}
|
||||||
addLine("try");
|
addLine("try");
|
||||||
@ -434,8 +494,15 @@ bool Why3Translator::visit(TupleExpression const& _node)
|
|||||||
|
|
||||||
bool Why3Translator::visit(UnaryOperation const& _unaryOperation)
|
bool Why3Translator::visit(UnaryOperation const& _unaryOperation)
|
||||||
{
|
{
|
||||||
if (toFormalType(*_unaryOperation.annotation().type).empty())
|
try
|
||||||
error(_unaryOperation, "Type not supported in unary operation.");
|
{
|
||||||
|
toFormalType(*_unaryOperation.annotation().type);
|
||||||
|
}
|
||||||
|
catch (NoFormalType &err)
|
||||||
|
{
|
||||||
|
string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
|
||||||
|
error(_unaryOperation, "Type \"" + (typeNamePtr ? *typeNamePtr : "") + "\" supported in unary operation.");
|
||||||
|
}
|
||||||
|
|
||||||
switch (_unaryOperation.getOperator())
|
switch (_unaryOperation.getOperator())
|
||||||
{
|
{
|
||||||
@ -798,5 +865,14 @@ module UInt256
|
|||||||
type t = uint256,
|
type t = uint256,
|
||||||
constant max = max_uint256
|
constant max = max_uint256
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Address
|
||||||
|
use import mach.int.Unsigned
|
||||||
|
type address
|
||||||
|
constant max_address: int = 0xffffffffffffffffffffffffffffffffffffffff (* 160 bit = 40 f's *)
|
||||||
|
clone export mach.int.Unsigned with
|
||||||
|
type t = address,
|
||||||
|
constant max = max_address
|
||||||
|
end
|
||||||
)", 0});
|
)", 0});
|
||||||
}
|
}
|
||||||
|
@ -60,9 +60,10 @@ private:
|
|||||||
/// Appends imports and constants use throughout the formal code.
|
/// Appends imports and constants use throughout the formal code.
|
||||||
void appendPreface();
|
void appendPreface();
|
||||||
|
|
||||||
/// @returns a string representation of the corresponding formal type or the empty string
|
/// @returns a string representation of the corresponding formal type or throws NoFormalType exception.
|
||||||
/// if the type is not supported.
|
|
||||||
std::string toFormalType(Type const& _type) const;
|
std::string toFormalType(Type const& _type) const;
|
||||||
|
using errinfo_noFormalTypeFrom = boost::error_info<struct tag_noFormalTypeFrom, std::string /* name of the type that cannot be translated */ >;
|
||||||
|
struct NoFormalType: virtual Exception {};
|
||||||
|
|
||||||
void indent() { newLine(); m_lines.back().indentation++; }
|
void indent() { newLine(); m_lines.back().indentation++; }
|
||||||
void unindent();
|
void unindent();
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [[ "$OSTYPE" != "darwin"* ]]; then
|
if [[ "$OSTYPE" != "darwin"* ]]; then
|
||||||
date -u +"nightly.%Y.%m.%d" > prerelease.txt
|
date -u +"nightly.%Y.%-m.%-d" > prerelease.txt
|
||||||
./scripts/travis-emscripten/install_deps.sh
|
./scripts/travis-emscripten/install_deps.sh
|
||||||
docker run -v $(pwd):/src trzeci/emscripten:sdk-tag-1.35.4-64bit ./scripts/travis-emscripten/build_emscripten.sh
|
docker run -v $(pwd):/src trzeci/emscripten:sdk-tag-1.35.4-64bit ./scripts/travis-emscripten/build_emscripten.sh
|
||||||
fi
|
fi
|
||||||
|
@ -56,6 +56,8 @@ detect_linux_distro() {
|
|||||||
elif [ -f /etc/os-release ]; then
|
elif [ -f /etc/os-release ]; then
|
||||||
# extract 'foo' from NAME=foo, only on the line with NAME=foo
|
# extract 'foo' from NAME=foo, only on the line with NAME=foo
|
||||||
DISTRO=$(sed -n -e 's/^NAME="\(.*\)\"/\1/p' /etc/os-release)
|
DISTRO=$(sed -n -e 's/^NAME="\(.*\)\"/\1/p' /etc/os-release)
|
||||||
|
elif [ -f /etc/centos-release ]; then
|
||||||
|
DISTRO=CentOS
|
||||||
else
|
else
|
||||||
DISTRO=''
|
DISTRO=''
|
||||||
fi
|
fi
|
||||||
@ -329,6 +331,51 @@ case $(uname -s) in
|
|||||||
sudo apt-get -y install eth
|
sudo apt-get -y install eth
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# CentOS
|
||||||
|
# CentOS needs some more testing. This is the general idea of packages
|
||||||
|
# needed, but some tweaking/improvements can definitely happen
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
CentOS)
|
||||||
|
read -p "This script will heavily modify your system in order to allow for compilation of Solidity. Are you sure? [Y/N]" -n 1 -r
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
# Make Sure we have the EPEL repos
|
||||||
|
sudo yum -y install epel-release
|
||||||
|
# Get g++ 4.8
|
||||||
|
sudo rpm --import http://ftp.scientificlinux.org/linux/scientific/5x/x86_64/RPM-GPG-KEYs/RPM-GPG-KEY-cern
|
||||||
|
wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo
|
||||||
|
sudo yum -y install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils
|
||||||
|
|
||||||
|
# Enable the devtoolset2 usage so global gcc/g++ become the 4.8 one.
|
||||||
|
# As per https://gist.github.com/stephenturner/e3bc5cfacc2dc67eca8b, what you should do afterwards is
|
||||||
|
# to add this line:
|
||||||
|
# source /opt/rh/devtoolset-2/enable
|
||||||
|
# to your bashrc so that this happens automatically at login
|
||||||
|
scl enable devtoolset-2 bash
|
||||||
|
|
||||||
|
# Get cmake
|
||||||
|
sudo yum -y remove cmake
|
||||||
|
sudo yum -y install cmake3
|
||||||
|
sudo ln -s /usr/bin/cmake3 /usr/bin/cmake
|
||||||
|
|
||||||
|
# Get latest boost thanks to this guy: http://vicendominguez.blogspot.de/2014/04/boost-c-library-rpm-packages-for-centos.html
|
||||||
|
sudo yum -y remove boost-devel
|
||||||
|
sudo wget http://repo.enetres.net/enetres.repo -O /etc/yum.repos.d/enetres.repo
|
||||||
|
sudo yum install boost-devel
|
||||||
|
|
||||||
|
# And finally jsoncpp
|
||||||
|
sudo yum -y install jsoncpp-devel
|
||||||
|
else
|
||||||
|
echo "Aborted CentOS Solidity Dependency Installation";
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
;;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*)
|
*)
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
@ -52,9 +52,9 @@ mv solidity solc
|
|||||||
# Determine version
|
# Determine version
|
||||||
cd solc
|
cd solc
|
||||||
version=`grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")"? CMakeLists.txt`
|
version=`grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")"? CMakeLists.txt`
|
||||||
commithash=`git rev-parse --short HEAD`
|
commithash=`git rev-parse --short=8 HEAD`
|
||||||
committimestamp=`git show --format=%ci HEAD | head -n 1`
|
committimestamp=`git show --format=%ci HEAD | head -n 1`
|
||||||
commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10`
|
commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./'`
|
||||||
|
|
||||||
echo "$commithash" > commit_hash.txt
|
echo "$commithash" > commit_hash.txt
|
||||||
if [ $branch = develop ]
|
if [ $branch = develop ]
|
||||||
|
@ -33,8 +33,11 @@ set -e
|
|||||||
VER=$(cat CMakeLists.txt | grep 'set(PROJECT_VERSION' | sed -e 's/.*set(PROJECT_VERSION "\(.*\)".*/\1/')
|
VER=$(cat CMakeLists.txt | grep 'set(PROJECT_VERSION' | sed -e 's/.*set(PROJECT_VERSION "\(.*\)".*/\1/')
|
||||||
test -n "$VER"
|
test -n "$VER"
|
||||||
VER="v$VER"
|
VER="v$VER"
|
||||||
COMMIT=$(git rev-parse --short HEAD)
|
COMMIT=$(git rev-parse --short=8 HEAD)
|
||||||
DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%m.%d)
|
DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%-m.%-d)
|
||||||
|
|
||||||
|
# remove leading zeros in components - they are not semver-compatible
|
||||||
|
COMMIT=$(echo "$COMMIT" | sed -e 's/^0*//')
|
||||||
|
|
||||||
ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
|
ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
|
||||||
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
|
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
|
||||||
|
@ -7144,6 +7144,23 @@ BOOST_AUTO_TEST_CASE(payable_function)
|
|||||||
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
|
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(payable_function_calls_library)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
library L {
|
||||||
|
function f() returns (uint) { return 7; }
|
||||||
|
}
|
||||||
|
contract C {
|
||||||
|
function f() payable returns (uint) {
|
||||||
|
return L.f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode, 0, "L");
|
||||||
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}});
|
||||||
|
BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7)));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(non_payable_throw)
|
BOOST_AUTO_TEST_CASE(non_payable_throw)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
@ -7186,6 +7203,33 @@ BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier)
|
|||||||
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
|
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
|
||||||
|
{
|
||||||
|
// This tests that memory resize for return values is not paid during the call, which would
|
||||||
|
// make the gas calculation overly complex. We access the end of the output area before
|
||||||
|
// the call is made.
|
||||||
|
// Tests that this also survives the optimizer.
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract C {
|
||||||
|
function f() returns (uint[200]) {}
|
||||||
|
}
|
||||||
|
contract D {
|
||||||
|
function f(C c) returns (uint) { c.f(); return 7; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
compileAndRun(sourceCode, 0, "C");
|
||||||
|
u160 cAddr = m_contractAddress;
|
||||||
|
compileAndRun(sourceCode, 0, "D");
|
||||||
|
BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7)));
|
||||||
|
|
||||||
|
m_optimize = true;
|
||||||
|
|
||||||
|
compileAndRun(sourceCode, 0, "C");
|
||||||
|
u160 cAddrOpt = m_contractAddress;
|
||||||
|
compileAndRun(sourceCode, 0, "D");
|
||||||
|
BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7)));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
@ -4009,6 +4009,16 @@ BOOST_AUTO_TEST_CASE(external_constructor)
|
|||||||
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
|
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract test {
|
||||||
|
struct S { uint x; }
|
||||||
|
function test(uint k) { S[k]; }
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user