aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/analysis/GlobalContext.cpp4
-rw-r--r--libsolidity/ast/Types.h2
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp14
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp18
4 files changed, 38 insertions, 0 deletions
diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp
index 20f8272f..d519934d 100644
--- a/libsolidity/analysis/GlobalContext.cpp
+++ b/libsolidity/analysis/GlobalContext.cpp
@@ -40,6 +40,10 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{make_shared<
make_shared<MagicVariableDeclaration>("now", make_shared<IntegerType>(256)),
make_shared<MagicVariableDeclaration>("suicide",
make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Location::Suicide)),
+ make_shared<MagicVariableDeclaration>("addmod",
+ make_shared<FunctionType>(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Location::AddMod)),
+ make_shared<MagicVariableDeclaration>("mulmod",
+ make_shared<FunctionType>(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Location::MulMod)),
make_shared<MagicVariableDeclaration>("sha3",
make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Location::SHA3, true)),
make_shared<MagicVariableDeclaration>("log0",
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 2f75975f..59c84b7a 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -747,6 +747,8 @@ public:
SetGas, ///< modify the default gas value for the function call
SetValue, ///< modify the default value transfer for the function call
BlockHash, ///< BLOCKHASH
+ AddMod, ///< ADDMOD
+ MulMod, ///< MULMOD
ArrayPush, ///< .push() to a dynamically sized array in storage
ByteArrayPush ///< .push() to a dynamically sized byte array in storage
};
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 3906a897..0f952f9c 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -637,6 +637,20 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << eth::Instruction::BLOCKHASH;
break;
}
+ case Location::AddMod:
+ case Location::MulMod:
+ {
+ for (unsigned i = 0; i < 3; i ++)
+ {
+ arguments[2 - i]->accept(*this);
+ utils().convertType(*arguments[2 - i]->annotation().type, IntegerType(256));
+ }
+ if (function.location() == Location::AddMod)
+ m_context << eth::Instruction::ADDMOD;
+ else
+ m_context << eth::Instruction::MULMOD;
+ break;
+ }
case Location::ECRecover:
case Location::SHA256:
case Location::RIPEMD160:
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index f2aa2e8e..20fef48d 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -5831,6 +5831,24 @@ BOOST_AUTO_TEST_CASE(memory_overwrite)
BOOST_CHECK(callContractFunction("f()") == encodeDyn(string("b23a5")));
}
+BOOST_AUTO_TEST_CASE(addmod_mulmod)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function test() returns (uint) {
+ // Note that this only works because computation on literals is done using
+ // unbounded integers.
+ if ((2**255 + 2**255) % 7 != addmod(2**255, 2**255, 7))
+ return 1;
+ if ((2**255 + 2**255) % 7 != addmod(2**255, 2**255, 7))
+ return 2;
+ return 0;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0)));
+}
BOOST_AUTO_TEST_SUITE_END()
}