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
|
||||
*.slo
|
||||
*.lo
|
||||
|
@ -8,7 +8,7 @@ include(EthPolicy)
|
||||
eth_policy()
|
||||
|
||||
# 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})
|
||||
|
||||
# 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)
|
||||
|
||||
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)
|
||||
else()
|
||||
string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC)
|
||||
string(REPLACE .0 . SOL_VERSION_PRERELEASE "${SOL_VERSION_PRERELEASE}")
|
||||
endif()
|
||||
|
||||
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)
|
||||
else()
|
||||
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
|
||||
)
|
||||
execute_process(
|
||||
@ -47,14 +48,17 @@ if (SOL_COMMIT_HASH)
|
||||
string(SUBSTRING ${SOL_COMMIT_HASH} 0 8 SOL_COMMIT_HASH)
|
||||
endif()
|
||||
|
||||
if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES)
|
||||
set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod")
|
||||
endif()
|
||||
|
||||
if (NOT SOL_COMMIT_HASH)
|
||||
message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or "
|
||||
"supply a file called commit_hash.txt")
|
||||
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}")
|
||||
|
||||
|
@ -56,9 +56,9 @@ copyright = '2016, Ethereum'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.2.0'
|
||||
version = '0.4.1'
|
||||
# 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
|
||||
# for a list of supported languages.
|
||||
|
@ -6,6 +6,15 @@
|
||||
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
|
||||
================
|
||||
|
||||
@ -186,3 +195,20 @@ Alternatively, you can build for Windows on the command-line, like so:
|
||||
.. code:: bash
|
||||
|
||||
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.");
|
||||
/// Do NOT supply an exception object as the second parameter.
|
||||
#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>;
|
||||
|
||||
@ -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)
|
||||
));
|
||||
else
|
||||
typeError(index->location(), "Integer constant expected.");
|
||||
fatalTypeError(index->location(), "Integer constant expected.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -263,7 +263,9 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
||||
CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration());
|
||||
|
||||
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.
|
||||
m_context << Instruction::CALLVALUE;
|
||||
|
@ -1476,6 +1476,18 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
||||
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.
|
||||
utils().fetchFreeMemoryPointer();
|
||||
if (!_functionType.isBareCall() || manualFunctionId)
|
||||
@ -1551,10 +1563,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
||||
gasNeededByCaller += eth::GasCosts::callValueTransferGas;
|
||||
if (!isCallCode && !isDelegateCall && !existenceChecked)
|
||||
gasNeededByCaller += eth::GasCosts::callNewAccountGas; // we never know
|
||||
m_context <<
|
||||
gasNeededByCaller <<
|
||||
Instruction::GAS <<
|
||||
Instruction::SUB;
|
||||
m_context << gasNeededByCaller << Instruction::GAS << Instruction::SUB;
|
||||
}
|
||||
if (isDelegateCall)
|
||||
m_context << Instruction::DELEGATECALL;
|
||||
|
@ -36,6 +36,10 @@ bool Why3Translator::process(SourceUnit const& _source)
|
||||
appendPreface();
|
||||
_source.accept(*this);
|
||||
}
|
||||
catch (NoFormalType&)
|
||||
{
|
||||
solAssert(false, "There is a call to toFormalType() that does not catch NoFormalType exceptions.");
|
||||
}
|
||||
catch (FatalError& /*_e*/)
|
||||
{
|
||||
solAssert(m_errorOccured, "");
|
||||
@ -77,14 +81,30 @@ string Why3Translator::toFormalType(Type const& _type) const
|
||||
return "uint256";
|
||||
}
|
||||
else if (auto type = dynamic_cast<ArrayType const*>(&_type))
|
||||
{
|
||||
if (!type->isByteArray() && type->isDynamicallySized() && type->dataStoredIn(DataLocation::Memory))
|
||||
{
|
||||
// Not catching NoFormalType exception. Let the caller deal with it.
|
||||
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)
|
||||
@ -142,9 +162,17 @@ bool Why3Translator::visit(ContractDefinition const& _contract)
|
||||
m_currentContract.stateVariables = _contract.stateVariables();
|
||||
for (VariableDeclaration const* variable: m_currentContract.stateVariables)
|
||||
{
|
||||
string varType = toFormalType(*variable->annotation().type);
|
||||
if (varType.empty())
|
||||
fatalError(*variable, "Type not supported for state variable.");
|
||||
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();
|
||||
@ -218,9 +246,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
|
||||
add(" (this: account)");
|
||||
for (auto const& param: _function.parameters())
|
||||
{
|
||||
string paramType = toFormalType(*param->annotation().type);
|
||||
if (paramType.empty())
|
||||
error(*param, "Parameter type not supported.");
|
||||
string paramType;
|
||||
try
|
||||
{
|
||||
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())
|
||||
error(*param, "Anonymous function parameters not supported.");
|
||||
add(" (arg_" + param->name() + ": " + paramType + ")");
|
||||
@ -232,9 +267,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
|
||||
string retString = "(";
|
||||
for (auto const& retParam: _function.returnParameters())
|
||||
{
|
||||
string paramType = toFormalType(*retParam->annotation().type);
|
||||
if (paramType.empty())
|
||||
error(*retParam, "Parameter type not supported.");
|
||||
string paramType;
|
||||
try
|
||||
{
|
||||
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)
|
||||
retString += ", ";
|
||||
retString += paramType;
|
||||
@ -264,14 +306,32 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
|
||||
{
|
||||
if (variable->name().empty())
|
||||
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");
|
||||
}
|
||||
for (VariableDeclaration const* variable: _function.localVariables())
|
||||
{
|
||||
if (variable->name().empty())
|
||||
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("try");
|
||||
@ -434,8 +494,15 @@ bool Why3Translator::visit(TupleExpression const& _node)
|
||||
|
||||
bool Why3Translator::visit(UnaryOperation const& _unaryOperation)
|
||||
{
|
||||
if (toFormalType(*_unaryOperation.annotation().type).empty())
|
||||
error(_unaryOperation, "Type not supported in unary operation.");
|
||||
try
|
||||
{
|
||||
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())
|
||||
{
|
||||
@ -798,5 +865,14 @@ module UInt256
|
||||
type t = uint256,
|
||||
constant max = max_uint256
|
||||
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});
|
||||
}
|
||||
|
@ -60,9 +60,10 @@ private:
|
||||
/// Appends imports and constants use throughout the formal code.
|
||||
void appendPreface();
|
||||
|
||||
/// @returns a string representation of the corresponding formal type or the empty string
|
||||
/// if the type is not supported.
|
||||
/// @returns a string representation of the corresponding formal type or throws NoFormalType exception.
|
||||
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 unindent();
|
||||
|
@ -29,7 +29,7 @@
|
||||
set -e
|
||||
|
||||
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
|
||||
docker run -v $(pwd):/src trzeci/emscripten:sdk-tag-1.35.4-64bit ./scripts/travis-emscripten/build_emscripten.sh
|
||||
fi
|
||||
|
@ -56,6 +56,8 @@ detect_linux_distro() {
|
||||
elif [ -f /etc/os-release ]; then
|
||||
# extract 'foo' from NAME=foo, only on the line with NAME=foo
|
||||
DISTRO=$(sed -n -e 's/^NAME="\(.*\)\"/\1/p' /etc/os-release)
|
||||
elif [ -f /etc/centos-release ]; then
|
||||
DISTRO=CentOS
|
||||
else
|
||||
DISTRO=''
|
||||
fi
|
||||
@ -329,6 +331,51 @@ case $(uname -s) in
|
||||
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
|
||||
cd solc
|
||||
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`
|
||||
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
|
||||
if [ $branch = develop ]
|
||||
|
@ -33,8 +33,11 @@ set -e
|
||||
VER=$(cat CMakeLists.txt | grep 'set(PROJECT_VERSION' | sed -e 's/.*set(PROJECT_VERSION "\(.*\)".*/\1/')
|
||||
test -n "$VER"
|
||||
VER="v$VER"
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%m.%d)
|
||||
COMMIT=$(git rev-parse --short=8 HEAD)
|
||||
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_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_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)
|
||||
{
|
||||
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_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()
|
||||
|
||||
|
@ -4009,6 +4009,16 @@ BOOST_AUTO_TEST_CASE(external_constructor)
|
||||
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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user