Skip to content

Commit 23c4142

Browse files
chrisethaxic
authored andcommitted
Bare functions take single bytes argument.
1 parent 0e66a1d commit 23c4142

5 files changed

Lines changed: 44 additions & 94 deletions

File tree

libsolidity/analysis/GlobalContext.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{
4242
make_shared<MagicVariableDeclaration>("blockhash", make_shared<FunctionType>(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)),
4343
make_shared<MagicVariableDeclaration>("ecrecover", make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)),
4444
make_shared<MagicVariableDeclaration>("gasleft", make_shared<FunctionType>(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)),
45-
make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)),
45+
make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA3, false, StateMutability::Pure)),
4646
make_shared<MagicVariableDeclaration>("log0", make_shared<FunctionType>(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)),
4747
make_shared<MagicVariableDeclaration>("log1", make_shared<FunctionType>(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)),
4848
make_shared<MagicVariableDeclaration>("log2", make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)),
@@ -55,10 +55,10 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{
5555
make_shared<MagicVariableDeclaration>("require", make_shared<FunctionType>(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
5656
make_shared<MagicVariableDeclaration>("revert", make_shared<FunctionType>(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
5757
make_shared<MagicVariableDeclaration>("revert", make_shared<FunctionType>(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
58-
make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)),
58+
make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)),
5959
make_shared<MagicVariableDeclaration>("selfdestruct", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)),
60-
make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)),
61-
make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)),
60+
make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)),
61+
make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA3, false, StateMutability::Pure)),
6262
make_shared<MagicVariableDeclaration>("suicide", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)),
6363
make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::Transaction))
6464
})

libsolidity/analysis/TypeChecker.cpp

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,35 +1750,6 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
17501750
}
17511751
}
17521752

1753-
if (functionType->takesSinglePackedBytesParameter())
1754-
{
1755-
if (
1756-
(arguments.size() > 1) ||
1757-
(arguments.size() == 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory)))
1758-
)
1759-
{
1760-
string msg =
1761-
"This function only accepts a single \"bytes\" argument. Please use "
1762-
"\"abi.encodePacked(...)\" or a similar function to encode the data.";
1763-
if (v050)
1764-
m_errorReporter.typeError(_functionCall.location(), msg);
1765-
else
1766-
m_errorReporter.warning(_functionCall.location(), msg);
1767-
}
1768-
1769-
if (arguments.size() == 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory)))
1770-
{
1771-
string msg =
1772-
"The provided argument of type " +
1773-
type(*arguments.front())->toString() +
1774-
" is not implicitly convertible to expected type bytes memory.";
1775-
if (v050)
1776-
m_errorReporter.typeError(_functionCall.location(), msg);
1777-
else
1778-
m_errorReporter.warning(_functionCall.location(), msg);
1779-
}
1780-
}
1781-
17821753
if (functionType->takesArbitraryParameters() && arguments.size() < parameterTypes.size())
17831754
{
17841755
solAssert(_functionCall.annotation().kind == FunctionCallKind::FunctionCall, "");

libsolidity/ast/Types.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,9 +599,9 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons
599599
if (isAddress())
600600
return {
601601
{"balance", make_shared<IntegerType>(256)},
602-
{"call", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Kind::BareCall, true, StateMutability::Payable)},
603-
{"callcode", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Kind::BareCallCode, true, StateMutability::Payable)},
604-
{"delegatecall", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Kind::BareDelegateCall, true)},
602+
{"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCall, true, StateMutability::Payable)},
603+
{"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCallCode, true, StateMutability::Payable)},
604+
{"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareDelegateCall, true)},
605605
{"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)},
606606
{"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)}
607607
};
@@ -3001,6 +3001,25 @@ ASTPointer<ASTString> FunctionType::documentation() const
30013001
return ASTPointer<ASTString>();
30023002
}
30033003

3004+
bool FunctionType::padArguments() const
3005+
{
3006+
// No padding only for hash functions, low-level calls and the packed encoding function.
3007+
switch (m_kind)
3008+
{
3009+
case Kind::BareCall:
3010+
case Kind::BareCallCode:
3011+
case Kind::BareDelegateCall:
3012+
case Kind::SHA256:
3013+
case Kind::RIPEMD160:
3014+
case Kind::SHA3:
3015+
case Kind::ABIEncodePacked:
3016+
return false;
3017+
default:
3018+
return true;
3019+
}
3020+
return true;
3021+
}
3022+
30043023
string MappingType::richIdentifier() const
30053024
{
30063025
return "t_mapping" + identifierList(m_keyType, m_valueType);

libsolidity/ast/Types.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,8 +1058,9 @@ class FunctionType: public Type
10581058
ASTPointer<ASTString> documentation() const;
10591059

10601060
/// true iff arguments are to be padded to multiples of 32 bytes for external calls
1061-
/// TODO should this be true in general for bareCall*?
1062-
bool padArguments() const { return !(m_kind == Kind::SHA3 || m_kind == Kind::SHA256 || m_kind == Kind::RIPEMD160 || m_kind == Kind::ABIEncodePacked); }
1061+
/// The only functions that do not pad are hash functions, the low-level call functions
1062+
/// and abi.encodePacked.
1063+
bool padArguments() const;
10631064
bool takesArbitraryParameters() const { return m_arbitraryParameters; }
10641065
/// true iff the function takes a single bytes parameter and it is passed on without padding.
10651066
bool takesSinglePackedBytesParameter() const

libsolidity/codegen/ExpressionCompiler.cpp

Lines changed: 15 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,39 +1837,12 @@ void ExpressionCompiler::appendExternalFunctionCall(
18371837
// Evaluate arguments.
18381838
TypePointers argumentTypes;
18391839
TypePointers parameterTypes = _functionType.parameterTypes();
1840-
// This can be removed (will always be false) with 0.5.0
1841-
bool manualFunctionId = false;
1842-
if (
1843-
(funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall) &&
1844-
!_arguments.empty()
1845-
)
1846-
{
1847-
solAssert(_arguments.front()->annotation().type->mobileType(), "");
1848-
manualFunctionId =
1849-
_arguments.front()->annotation().type->mobileType()->calldataEncodedSize(false) ==
1850-
CompilerUtils::dataStartOffset;
1851-
}
1852-
if (manualFunctionId)
1853-
{
1854-
// If we have a Bare* and the first type has exactly 4 bytes, use it as
1855-
// function identifier.
1856-
_arguments.front()->accept(*this);
1857-
utils().convertType(
1858-
*_arguments.front()->annotation().type,
1859-
IntegerType(8 * CompilerUtils::dataStartOffset),
1860-
true
1861-
);
1862-
for (unsigned i = 0; i < gasValueSize; ++i)
1863-
m_context << swapInstruction(gasValueSize - i);
1864-
gasStackPos++;
1865-
valueStackPos++;
1866-
}
18671840
if (_functionType.bound())
18681841
{
18691842
argumentTypes.push_back(_functionType.selfType());
18701843
parameterTypes.insert(parameterTypes.begin(), _functionType.selfType());
18711844
}
1872-
for (size_t i = manualFunctionId ? 1 : 0; i < _arguments.size(); ++i)
1845+
for (size_t i = 0; i < _arguments.size(); ++i)
18731846
{
18741847
_arguments[i]->accept(*this);
18751848
argumentTypes.push_back(_arguments[i]->annotation().type);
@@ -1905,36 +1878,22 @@ void ExpressionCompiler::appendExternalFunctionCall(
19051878

19061879
// Copy function identifier to memory.
19071880
utils().fetchFreeMemoryPointer();
1908-
if (!_functionType.isBareCall() || manualFunctionId)
1881+
if (!_functionType.isBareCall())
19091882
{
19101883
m_context << dupInstruction(2 + gasValueSize + CompilerUtils::sizeOnStack(argumentTypes));
19111884
utils().storeInMemoryDynamic(IntegerType(8 * CompilerUtils::dataStartOffset), false);
19121885
}
19131886

1914-
// This is a function that takes a single bytes parameter which is supposed to be passed
1915-
// on inline and without padding.
1916-
if (_functionType.takesSinglePackedBytesParameter() && v050 && argumentTypes.size() == 1)
1917-
{
1918-
utils().encodeToMemory(
1919-
argumentTypes,
1920-
TypePointers{make_shared<ArrayType>(DataLocation::Memory)},
1921-
false,
1922-
true
1923-
);
1924-
}
1925-
else
1926-
{
1927-
// If the function takes arbitrary parameters, copy dynamic length data in place.
1928-
// Move arguments to memory, will not update the free memory pointer (but will update the memory
1929-
// pointer on the stack).
1930-
utils().encodeToMemory(
1931-
argumentTypes,
1932-
parameterTypes,
1933-
_functionType.padArguments(),
1934-
_functionType.takesArbitraryParameters(),
1935-
isCallCode || isDelegateCall
1936-
);
1937-
}
1887+
// If the function takes arbitrary parameters or is a bare call, copy dynamic length data in place.
1888+
// Move arguments to memory, will not update the free memory pointer (but will update the memory
1889+
// pointer on the stack).
1890+
utils().encodeToMemory(
1891+
argumentTypes,
1892+
parameterTypes,
1893+
_functionType.padArguments(),
1894+
_functionType.takesArbitraryParameters() || _functionType.isBareCall(),
1895+
isCallCode || isDelegateCall
1896+
);
19381897

19391898
// Stack now:
19401899
// <stack top>
@@ -2013,9 +1972,9 @@ void ExpressionCompiler::appendExternalFunctionCall(
20131972

20141973
unsigned remainsSize =
20151974
2 + // contract address, input_memory_end
2016-
_functionType.valueSet() +
2017-
_functionType.gasSet() +
2018-
(!_functionType.isBareCall() || manualFunctionId);
1975+
(_functionType.valueSet() ? 1 : 0) +
1976+
(_functionType.gasSet() ? 1 : 0) +
1977+
(!_functionType.isBareCall() ? 1 : 0);
20191978

20201979
if (returnSuccessCondition)
20211980
m_context << swapInstruction(remainsSize);

0 commit comments

Comments
 (0)