mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add this and state to CHC
This commit is contained in:
parent
a86f656704
commit
18cf01c187
@ -396,7 +396,6 @@ void BMC::endVisit(FunctionCall const& _funCall)
|
|||||||
case FunctionType::Kind::Send:
|
case FunctionType::Kind::Send:
|
||||||
case FunctionType::Kind::Transfer:
|
case FunctionType::Kind::Transfer:
|
||||||
{
|
{
|
||||||
SMTEncoder::endVisit(_funCall);
|
|
||||||
auto value = _funCall.arguments().front();
|
auto value = _funCall.arguments().front();
|
||||||
solAssert(value, "");
|
solAssert(value, "");
|
||||||
smtutil::Expression thisBalance = m_context.state().balance();
|
smtutil::Expression thisBalance = m_context.state().balance();
|
||||||
@ -406,6 +405,8 @@ void BMC::endVisit(FunctionCall const& _funCall)
|
|||||||
thisBalance < expr(*value),
|
thisBalance < expr(*value),
|
||||||
&_funCall
|
&_funCall
|
||||||
);
|
);
|
||||||
|
|
||||||
|
SMTEncoder::endVisit(_funCall);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::AddMod:
|
case FunctionType::Kind::AddMod:
|
||||||
|
@ -101,7 +101,7 @@ bool CHC::visit(ContractDefinition const& _contract)
|
|||||||
|
|
||||||
solAssert(m_currentContract, "");
|
solAssert(m_currentContract, "");
|
||||||
m_constructorSummaryPredicate = createSymbolicBlock(
|
m_constructorSummaryPredicate = createSymbolicBlock(
|
||||||
constructorSort(*m_currentContract),
|
constructorSort(*m_currentContract, state()),
|
||||||
"summary_constructor_" + contractSuffix(_contract),
|
"summary_constructor_" + contractSuffix(_contract),
|
||||||
PredicateType::ConstructorSummary,
|
PredicateType::ConstructorSummary,
|
||||||
&_contract
|
&_contract
|
||||||
@ -114,15 +114,16 @@ bool CHC::visit(ContractDefinition const& _contract)
|
|||||||
void CHC::endVisit(ContractDefinition const& _contract)
|
void CHC::endVisit(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
auto implicitConstructorPredicate = createSymbolicBlock(
|
auto implicitConstructorPredicate = createSymbolicBlock(
|
||||||
implicitConstructorSort(),
|
implicitConstructorSort(state()),
|
||||||
"implicit_constructor_" + contractSuffix(_contract),
|
"implicit_constructor_" + contractSuffix(_contract),
|
||||||
PredicateType::ImplicitConstructor,
|
PredicateType::ImplicitConstructor,
|
||||||
&_contract
|
&_contract
|
||||||
);
|
);
|
||||||
auto implicitConstructor = (*implicitConstructorPredicate)({});
|
addRule(
|
||||||
addRule(implicitConstructor, implicitConstructor.name);
|
(*implicitConstructorPredicate)({0, state().thisAddress(), state().state()}),
|
||||||
m_currentBlock = implicitConstructor;
|
implicitConstructorPredicate->functor().name
|
||||||
m_context.addAssertion(errorFlag().currentValue() == 0);
|
);
|
||||||
|
setCurrentBlock(*implicitConstructorPredicate);
|
||||||
|
|
||||||
if (auto constructor = _contract.constructor())
|
if (auto constructor = _contract.constructor())
|
||||||
constructor->accept(*this);
|
constructor->accept(*this);
|
||||||
@ -178,6 +179,7 @@ bool CHC::visit(FunctionDefinition const& _function)
|
|||||||
m_context.addAssertion(m_context.variable(*var)->valueAtIndex(0) == currentValue(*var));
|
m_context.addAssertion(m_context.variable(*var)->valueAtIndex(0) == currentValue(*var));
|
||||||
for (auto const& var: _function.parameters())
|
for (auto const& var: _function.parameters())
|
||||||
m_context.addAssertion(m_context.variable(*var)->valueAtIndex(0) == currentValue(*var));
|
m_context.addAssertion(m_context.variable(*var)->valueAtIndex(0) == currentValue(*var));
|
||||||
|
m_context.addAssertion(state().state(0) == state().state());
|
||||||
|
|
||||||
connectBlocks(functionPred, bodyPred);
|
connectBlocks(functionPred, bodyPred);
|
||||||
|
|
||||||
@ -215,7 +217,7 @@ void CHC::endVisit(FunctionDefinition const& _function)
|
|||||||
string suffix = m_currentContract->name() + "_" + to_string(m_currentContract->id());
|
string suffix = m_currentContract->name() + "_" + to_string(m_currentContract->id());
|
||||||
solAssert(m_currentContract, "");
|
solAssert(m_currentContract, "");
|
||||||
auto constructorExit = createSymbolicBlock(
|
auto constructorExit = createSymbolicBlock(
|
||||||
constructorSort(*m_currentContract),
|
constructorSort(*m_currentContract, state()),
|
||||||
"constructor_exit_" + suffix,
|
"constructor_exit_" + suffix,
|
||||||
PredicateType::ConstructorSummary,
|
PredicateType::ConstructorSummary,
|
||||||
m_currentContract
|
m_currentContract
|
||||||
@ -234,7 +236,7 @@ void CHC::endVisit(FunctionDefinition const& _function)
|
|||||||
|
|
||||||
setCurrentBlock(*m_interfaces.at(m_currentContract));
|
setCurrentBlock(*m_interfaces.at(m_currentContract));
|
||||||
|
|
||||||
auto ifacePre = (*m_interfaces.at(m_currentContract))(initialStateVariables());
|
auto ifacePre = smt::interfacePre(*m_interfaces.at(m_currentContract), *m_currentContract, m_context);
|
||||||
if (_function.isPublic())
|
if (_function.isPublic())
|
||||||
{
|
{
|
||||||
addAssertVerificationTarget(&_function, ifacePre, sum, assertionError);
|
addAssertVerificationTarget(&_function, ifacePre, sum, assertionError);
|
||||||
@ -598,15 +600,21 @@ void CHC::externalFunctionCall(FunctionCall const& _funCall)
|
|||||||
for (auto var: function->returnParameters())
|
for (auto var: function->returnParameters())
|
||||||
m_context.variable(*var)->increaseIndex();
|
m_context.variable(*var)->increaseIndex();
|
||||||
|
|
||||||
auto preCallState = currentStateVariables();
|
auto preCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables();
|
||||||
bool usesStaticCall = kind == FunctionType::Kind::BareStaticCall ||
|
bool usesStaticCall = kind == FunctionType::Kind::BareStaticCall ||
|
||||||
function->stateMutability() == StateMutability::Pure ||
|
function->stateMutability() == StateMutability::Pure ||
|
||||||
function->stateMutability() == StateMutability::View;
|
function->stateMutability() == StateMutability::View;
|
||||||
if (!usesStaticCall)
|
if (!usesStaticCall)
|
||||||
|
{
|
||||||
|
state().newState();
|
||||||
for (auto const* var: m_stateVariables)
|
for (auto const* var: m_stateVariables)
|
||||||
m_context.variable(*var)->increaseIndex();
|
m_context.variable(*var)->increaseIndex();
|
||||||
|
}
|
||||||
|
|
||||||
auto nondet = (*m_nondetInterfaces.at(m_currentContract))(preCallState + currentStateVariables());
|
auto postCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables();
|
||||||
|
auto nondet = (*m_nondetInterfaces.at(m_currentContract))(preCallState + postCallState);
|
||||||
|
// TODO this could instead add the summary of the called function, where that summary
|
||||||
|
// basically has the nondet interface of this summary as a constraint.
|
||||||
m_context.addAssertion(nondet);
|
m_context.addAssertion(nondet);
|
||||||
|
|
||||||
m_context.addAssertion(errorFlag().currentValue() == 0);
|
m_context.addAssertion(errorFlag().currentValue() == 0);
|
||||||
@ -775,6 +783,8 @@ void CHC::clearIndices(ContractDefinition const* _contract, FunctionDefinition c
|
|||||||
for (auto const& var: _function->localVariables())
|
for (auto const& var: _function->localVariables())
|
||||||
m_context.variable(*var)->increaseIndex();
|
m_context.variable(*var)->increaseIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state().newState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHC::setCurrentBlock(Predicate const& _block)
|
void CHC::setCurrentBlock(Predicate const& _block)
|
||||||
@ -800,7 +810,7 @@ set<frontend::Expression const*, CHC::IdCompare> CHC::transactionAssertions(ASTN
|
|||||||
|
|
||||||
SortPointer CHC::sort(FunctionDefinition const& _function)
|
SortPointer CHC::sort(FunctionDefinition const& _function)
|
||||||
{
|
{
|
||||||
return functionSort(_function, m_currentContract);
|
return functionSort(_function, m_currentContract, state());
|
||||||
}
|
}
|
||||||
|
|
||||||
SortPointer CHC::sort(ASTNode const* _node)
|
SortPointer CHC::sort(ASTNode const* _node)
|
||||||
@ -809,7 +819,7 @@ SortPointer CHC::sort(ASTNode const* _node)
|
|||||||
return sort(*funDef);
|
return sort(*funDef);
|
||||||
|
|
||||||
solAssert(m_currentFunction, "");
|
solAssert(m_currentFunction, "");
|
||||||
return functionBodySort(*m_currentFunction, m_currentContract);
|
return functionBodySort(*m_currentFunction, m_currentContract, state());
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate const* CHC::createSymbolicBlock(SortPointer _sort, string const& _name, PredicateType _predType, ASTNode const* _node)
|
Predicate const* CHC::createSymbolicBlock(SortPointer _sort, string const& _name, PredicateType _predType, ASTNode const* _node)
|
||||||
@ -825,8 +835,8 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
|
|||||||
if (auto const* contract = dynamic_cast<ContractDefinition const*>(node.get()))
|
if (auto const* contract = dynamic_cast<ContractDefinition const*>(node.get()))
|
||||||
{
|
{
|
||||||
string suffix = contract->name() + "_" + to_string(contract->id());
|
string suffix = contract->name() + "_" + to_string(contract->id());
|
||||||
m_interfaces[contract] = createSymbolicBlock(interfaceSort(*contract), "interface_" + suffix, PredicateType::Interface, contract);
|
m_interfaces[contract] = createSymbolicBlock(interfaceSort(*contract, state()), "interface_" + suffix, PredicateType::Interface, contract);
|
||||||
m_nondetInterfaces[contract] = createSymbolicBlock(nondetInterfaceSort(*contract), "nondet_interface_" + suffix, PredicateType::NondetInterface, contract);
|
m_nondetInterfaces[contract] = createSymbolicBlock(nondetInterfaceSort(*contract, state()), "nondet_interface_" + suffix, PredicateType::NondetInterface, contract);
|
||||||
|
|
||||||
for (auto const* var: stateVariablesIncludingInheritedAndPrivate(*contract))
|
for (auto const* var: stateVariablesIncludingInheritedAndPrivate(*contract))
|
||||||
if (!m_context.knownVariable(*var))
|
if (!m_context.knownVariable(*var))
|
||||||
@ -836,8 +846,7 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
|
|||||||
/// 0 steps to be taken, used as base for the inductive
|
/// 0 steps to be taken, used as base for the inductive
|
||||||
/// rule for each function.
|
/// rule for each function.
|
||||||
auto const& iface = *m_nondetInterfaces.at(contract);
|
auto const& iface = *m_nondetInterfaces.at(contract);
|
||||||
auto state0 = stateVariablesAtIndex(0, *contract);
|
addRule(smt::nondetInterface(iface, *contract, m_context, 0, 0), "base_nondet");
|
||||||
addRule(iface(state0 + state0), "base_nondet");
|
|
||||||
|
|
||||||
for (auto const* base: contract->annotation().linearizedBaseContracts)
|
for (auto const* base: contract->annotation().linearizedBaseContracts)
|
||||||
for (auto const* function: base->definedFunctions())
|
for (auto const* function: base->definedFunctions())
|
||||||
@ -861,12 +870,13 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
|
|||||||
auto state1 = stateVariablesAtIndex(1, *contract);
|
auto state1 = stateVariablesAtIndex(1, *contract);
|
||||||
auto state2 = stateVariablesAtIndex(2, *contract);
|
auto state2 = stateVariablesAtIndex(2, *contract);
|
||||||
|
|
||||||
auto nondetPre = iface(state0 + state1);
|
auto nondetPre = smt::nondetInterface(iface, *contract, m_context, 0, 1);
|
||||||
auto nondetPost = iface(state0 + state2);
|
auto nondetPost = smt::nondetInterface(iface, *contract, m_context, 0, 2);
|
||||||
|
|
||||||
vector<smtutil::Expression> args{errorFlag().currentValue()};
|
vector<smtutil::Expression> args{errorFlag().currentValue(), state().thisAddress(), state().state(1)};
|
||||||
args += state1 +
|
args += state1 +
|
||||||
applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 0); }) +
|
applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 0); }) +
|
||||||
|
vector<smtutil::Expression>{state().state(2)} +
|
||||||
state2 +
|
state2 +
|
||||||
applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 1); }) +
|
applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 1); }) +
|
||||||
applyMap(function->returnParameters(), [this](auto _var) { return valueAtIndex(*_var, 1); });
|
applyMap(function->returnParameters(), [this](auto _var) { return valueAtIndex(*_var, 1); });
|
||||||
@ -930,7 +940,7 @@ Predicate const* CHC::createBlock(ASTNode const* _node, PredicateType _predType,
|
|||||||
Predicate const* CHC::createSummaryBlock(FunctionDefinition const& _function, ContractDefinition const& _contract)
|
Predicate const* CHC::createSummaryBlock(FunctionDefinition const& _function, ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
auto block = createSymbolicBlock(
|
auto block = createSymbolicBlock(
|
||||||
functionSort(_function, &_contract),
|
functionSort(_function, &_contract, state()),
|
||||||
"summary_" + uniquePrefix() + "_" + predicateName(&_function, &_contract),
|
"summary_" + uniquePrefix() + "_" + predicateName(&_function, &_contract),
|
||||||
PredicateType::FunctionSummary,
|
PredicateType::FunctionSummary,
|
||||||
&_function
|
&_function
|
||||||
@ -1042,7 +1052,7 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
|
|||||||
return smtutil::Expression(true);
|
return smtutil::Expression(true);
|
||||||
|
|
||||||
errorFlag().increaseIndex();
|
errorFlag().increaseIndex();
|
||||||
vector<smtutil::Expression> args{errorFlag().currentValue()};
|
vector<smtutil::Expression> args{errorFlag().currentValue(), state().thisAddress(), state().state()};
|
||||||
|
|
||||||
FunctionType const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
|
FunctionType const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
|
||||||
solAssert(funType.kind() == FunctionType::Kind::Internal, "");
|
solAssert(funType.kind() == FunctionType::Kind::Internal, "");
|
||||||
@ -1058,11 +1068,17 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
|
|||||||
auto const* calledContract = contract->isLibrary() ? contract : m_currentContract;
|
auto const* calledContract = contract->isLibrary() ? contract : m_currentContract;
|
||||||
solAssert(calledContract, "");
|
solAssert(calledContract, "");
|
||||||
|
|
||||||
|
bool usesStaticCall = function->stateMutability() == StateMutability::Pure || function->stateMutability() == StateMutability::View;
|
||||||
|
|
||||||
args += currentStateVariables(*calledContract);
|
args += currentStateVariables(*calledContract);
|
||||||
args += symbolicArguments(_funCall);
|
args += symbolicArguments(_funCall);
|
||||||
if (!calledContract->isLibrary())
|
if (!calledContract->isLibrary() && !usesStaticCall)
|
||||||
|
{
|
||||||
|
state().newState();
|
||||||
for (auto const& var: m_stateVariables)
|
for (auto const& var: m_stateVariables)
|
||||||
m_context.variable(*var)->increaseIndex();
|
m_context.variable(*var)->increaseIndex();
|
||||||
|
}
|
||||||
|
args += vector<smtutil::Expression>{state().state()};
|
||||||
args += currentStateVariables(*calledContract);
|
args += currentStateVariables(*calledContract);
|
||||||
|
|
||||||
for (auto var: function->parameters() + function->returnParameters())
|
for (auto var: function->parameters() + function->returnParameters())
|
||||||
@ -1152,7 +1168,7 @@ void CHC::addVerificationTarget(ASTNode const* _scope, VerificationTarget::Type
|
|||||||
addVerificationTarget(_scope, _type, summary(*m_currentContract), smtutil::Expression(true), _errorId);
|
addVerificationTarget(_scope, _type, summary(*m_currentContract), smtutil::Expression(true), _errorId);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto iface = (*m_interfaces.at(m_currentContract))(initialStateVariables());
|
auto iface = smt::interfacePre(*m_interfaces.at(m_currentContract), *m_currentContract, m_context);
|
||||||
auto sum = summary(*m_currentFunction);
|
auto sum = summary(*m_currentFunction);
|
||||||
addVerificationTarget(_scope, _type, iface, sum, _errorId);
|
addVerificationTarget(_scope, _type, iface, sum, _errorId);
|
||||||
}
|
}
|
||||||
@ -1444,7 +1460,12 @@ unsigned CHC::newErrorId(frontend::Expression const& _expr)
|
|||||||
return errorId;
|
return errorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolicState& CHC::state()
|
||||||
|
{
|
||||||
|
return m_context.state();
|
||||||
|
}
|
||||||
|
|
||||||
SymbolicIntVariable& CHC::errorFlag()
|
SymbolicIntVariable& CHC::errorFlag()
|
||||||
{
|
{
|
||||||
return m_context.state().errorFlag();
|
return state().errorFlag();
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,7 @@ private:
|
|||||||
/// it into m_errorIds.
|
/// it into m_errorIds.
|
||||||
unsigned newErrorId(Expression const& _expr);
|
unsigned newErrorId(Expression const& _expr);
|
||||||
|
|
||||||
|
smt::SymbolicState& state();
|
||||||
smt::SymbolicIntVariable& errorFlag();
|
smt::SymbolicIntVariable& errorFlag();
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
@ -161,9 +161,9 @@ string Predicate::formatSummaryCall(vector<string> const& _args) const
|
|||||||
auto const* fun = programFunction();
|
auto const* fun = programFunction();
|
||||||
solAssert(fun, "");
|
solAssert(fun, "");
|
||||||
|
|
||||||
/// The signature of a function summary predicate is: summary(error, preStateVars, preInputVars, postStateVars, postInputVars, outputVars).
|
/// The signature of a function summary predicate is: summary(error, this, preBlockChainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
|
||||||
/// Here we are interested in preInputVars.
|
/// Here we are interested in preInputVars.
|
||||||
vector<string>::const_iterator first = _args.begin() + static_cast<int>(stateVars->size()) + 1;
|
vector<string>::const_iterator first = _args.begin() + 3 + static_cast<int>(stateVars->size());
|
||||||
vector<string>::const_iterator last = first + static_cast<int>(fun->parameters().size());
|
vector<string>::const_iterator last = first + static_cast<int>(fun->parameters().size());
|
||||||
solAssert(first >= _args.begin() && first <= _args.end(), "");
|
solAssert(first >= _args.begin() && first <= _args.end(), "");
|
||||||
solAssert(last >= _args.begin() && last <= _args.end(), "");
|
solAssert(last >= _args.begin() && last <= _args.end(), "");
|
||||||
@ -188,8 +188,8 @@ string Predicate::formatSummaryCall(vector<string> const& _args) const
|
|||||||
|
|
||||||
vector<string> Predicate::summaryStateValues(vector<string> const& _args) const
|
vector<string> Predicate::summaryStateValues(vector<string> const& _args) const
|
||||||
{
|
{
|
||||||
/// The signature of a function summary predicate is: summary(error, preStateVars, preInputVars, postStateVars, postInputVars, outputVars).
|
/// The signature of a function summary predicate is: summary(error, this, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
|
||||||
/// The signature of an implicit constructor summary predicate is: summary(error, postStateVars).
|
/// The signature of an implicit constructor summary predicate is: summary(error, this, postBlockchainState, postStateVars).
|
||||||
/// Here we are interested in postStateVars.
|
/// Here we are interested in postStateVars.
|
||||||
|
|
||||||
auto stateVars = stateVariables();
|
auto stateVars = stateVariables();
|
||||||
@ -199,12 +199,12 @@ vector<string> Predicate::summaryStateValues(vector<string> const& _args) const
|
|||||||
vector<string>::const_iterator stateLast;
|
vector<string>::const_iterator stateLast;
|
||||||
if (auto const* function = programFunction())
|
if (auto const* function = programFunction())
|
||||||
{
|
{
|
||||||
stateFirst = _args.begin() + 1 + static_cast<int>(stateVars->size()) + static_cast<int>(function->parameters().size());
|
stateFirst = _args.begin() + 3 + static_cast<int>(stateVars->size()) + static_cast<int>(function->parameters().size()) + 1;
|
||||||
stateLast = stateFirst + static_cast<int>(stateVars->size());
|
stateLast = stateFirst + static_cast<int>(stateVars->size());
|
||||||
}
|
}
|
||||||
else if (programContract())
|
else if (programContract())
|
||||||
{
|
{
|
||||||
stateFirst = _args.begin() + 1;
|
stateFirst = _args.begin() + 3;
|
||||||
stateLast = stateFirst + static_cast<int>(stateVars->size());
|
stateLast = stateFirst + static_cast<int>(stateVars->size());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -220,7 +220,7 @@ vector<string> Predicate::summaryStateValues(vector<string> const& _args) const
|
|||||||
|
|
||||||
vector<string> Predicate::summaryPostInputValues(vector<string> const& _args) const
|
vector<string> Predicate::summaryPostInputValues(vector<string> const& _args) const
|
||||||
{
|
{
|
||||||
/// The signature of a function summary predicate is: summary(error, preStateVars, preInputVars, postStateVars, postInputVars, outputVars).
|
/// The signature of a function summary predicate is: summary(error, this, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
|
||||||
/// Here we are interested in postInputVars.
|
/// Here we are interested in postInputVars.
|
||||||
auto const* function = programFunction();
|
auto const* function = programFunction();
|
||||||
solAssert(function, "");
|
solAssert(function, "");
|
||||||
@ -230,7 +230,7 @@ vector<string> Predicate::summaryPostInputValues(vector<string> const& _args) co
|
|||||||
|
|
||||||
auto const& inParams = function->parameters();
|
auto const& inParams = function->parameters();
|
||||||
|
|
||||||
vector<string>::const_iterator first = _args.begin() + 1 + static_cast<int>(stateVars->size()) * 2 + static_cast<int>(inParams.size());
|
vector<string>::const_iterator first = _args.begin() + 3 + static_cast<int>(stateVars->size()) * 2 + static_cast<int>(inParams.size()) + 1;
|
||||||
vector<string>::const_iterator last = first + static_cast<int>(inParams.size());
|
vector<string>::const_iterator last = first + static_cast<int>(inParams.size());
|
||||||
|
|
||||||
solAssert(first >= _args.begin() && first <= _args.end(), "");
|
solAssert(first >= _args.begin() && first <= _args.end(), "");
|
||||||
@ -243,7 +243,7 @@ vector<string> Predicate::summaryPostInputValues(vector<string> const& _args) co
|
|||||||
|
|
||||||
vector<string> Predicate::summaryPostOutputValues(vector<string> const& _args) const
|
vector<string> Predicate::summaryPostOutputValues(vector<string> const& _args) const
|
||||||
{
|
{
|
||||||
/// The signature of a function summary predicate is: summary(error, preStateVars, preInputVars, postStateVars, postInputVars, outputVars).
|
/// The signature of a function summary predicate is: summary(error, this, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
|
||||||
/// Here we are interested in outputVars.
|
/// Here we are interested in outputVars.
|
||||||
auto const* function = programFunction();
|
auto const* function = programFunction();
|
||||||
solAssert(function, "");
|
solAssert(function, "");
|
||||||
@ -253,7 +253,7 @@ vector<string> Predicate::summaryPostOutputValues(vector<string> const& _args) c
|
|||||||
|
|
||||||
auto const& inParams = function->parameters();
|
auto const& inParams = function->parameters();
|
||||||
|
|
||||||
vector<string>::const_iterator first = _args.begin() + 1 + static_cast<int>(stateVars->size()) * 2 + static_cast<int>(inParams.size()) * 2;
|
vector<string>::const_iterator first = _args.begin() + 3 + static_cast<int>(stateVars->size()) * 2 + static_cast<int>(inParams.size()) * 2 + 1;
|
||||||
|
|
||||||
solAssert(first >= _args.begin() && first <= _args.end(), "");
|
solAssert(first >= _args.begin() && first <= _args.end(), "");
|
||||||
|
|
||||||
|
@ -27,10 +27,35 @@ using namespace solidity::smtutil;
|
|||||||
|
|
||||||
namespace solidity::frontend::smt
|
namespace solidity::frontend::smt
|
||||||
{
|
{
|
||||||
|
smtutil::Expression interfacePre(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
|
||||||
|
{
|
||||||
|
auto& state = _context.state();
|
||||||
|
vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.state(0)};
|
||||||
|
return _pred(stateExprs + initialStateVariables(_contract, _context));
|
||||||
|
}
|
||||||
|
|
||||||
smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
|
smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
|
||||||
{
|
{
|
||||||
return _pred(currentStateVariables(_contract, _context));
|
auto& state = _context.state();
|
||||||
|
vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.state()};
|
||||||
|
return _pred(stateExprs + currentStateVariables(_contract, _context));
|
||||||
|
}
|
||||||
|
|
||||||
|
smtutil::Expression nondetInterface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context, unsigned _preIdx, unsigned _postIdx)
|
||||||
|
{
|
||||||
|
return _pred(
|
||||||
|
vector<smtutil::Expression>{_context.state().state(_preIdx)} +
|
||||||
|
stateVariablesAtIndex(_preIdx, _contract, _context) +
|
||||||
|
vector<smtutil::Expression>{_context.state().state(_postIdx)} +
|
||||||
|
stateVariablesAtIndex(_postIdx, _contract, _context)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
smtutil::Expression implicitConstructor(Predicate const& _pred, ContractDefinition const&, EncodingContext& _context)
|
||||||
|
{
|
||||||
|
auto& state = _context.state();
|
||||||
|
vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(0), state.state(0)};
|
||||||
|
return _pred(stateExprs);
|
||||||
}
|
}
|
||||||
|
|
||||||
smtutil::Expression constructor(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
|
smtutil::Expression constructor(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
|
||||||
@ -38,16 +63,9 @@ smtutil::Expression constructor(Predicate const& _pred, ContractDefinition const
|
|||||||
if (auto const* constructor = _contract.constructor())
|
if (auto const* constructor = _contract.constructor())
|
||||||
return _pred(currentFunctionVariables(*constructor, &_contract, _context));
|
return _pred(currentFunctionVariables(*constructor, &_contract, _context));
|
||||||
|
|
||||||
return _pred(
|
auto& state = _context.state();
|
||||||
vector<smtutil::Expression>{_context.state().errorFlag().currentValue()} +
|
vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(0), state.state()};
|
||||||
currentStateVariables(_contract, _context)
|
return _pred(stateExprs + currentStateVariables(_contract, _context));
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Currently it does not have arguments but it will have tx data in the future.
|
|
||||||
smtutil::Expression implicitConstructor(Predicate const& _pred, ContractDefinition const&, EncodingContext&)
|
|
||||||
{
|
|
||||||
return _pred({});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
smtutil::Expression function(
|
smtutil::Expression function(
|
||||||
@ -99,9 +117,11 @@ vector<smtutil::Expression> currentFunctionVariables(
|
|||||||
EncodingContext& _context
|
EncodingContext& _context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
vector<smtutil::Expression> exprs{_context.state().errorFlag().currentValue()};
|
auto& state = _context.state();
|
||||||
|
vector<smtutil::Expression> exprs{_context.state().errorFlag().currentValue(), state.thisAddress(0), state.state(0)};
|
||||||
exprs += _contract ? initialStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
exprs += _contract ? initialStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
||||||
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->valueAtIndex(0); });
|
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->valueAtIndex(0); });
|
||||||
|
exprs += vector<smtutil::Expression>{state.state()};
|
||||||
exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
||||||
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
||||||
exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
||||||
|
@ -30,8 +30,12 @@ class EncodingContext;
|
|||||||
* The predicates follow the specification in PredicateSort.h.
|
* The predicates follow the specification in PredicateSort.h.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
smtutil::Expression interfacePre(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context);
|
||||||
|
|
||||||
smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context);
|
smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context);
|
||||||
|
|
||||||
|
smtutil::Expression nondetInterface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context, unsigned _preIdx, unsigned _postIdx);
|
||||||
|
|
||||||
smtutil::Expression constructor(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context);
|
smtutil::Expression constructor(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context);
|
||||||
|
|
||||||
smtutil::Expression implicitConstructor(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context);
|
smtutil::Expression implicitConstructor(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context);
|
||||||
|
@ -28,49 +28,54 @@ using namespace solidity::smtutil;
|
|||||||
namespace solidity::frontend::smt
|
namespace solidity::frontend::smt
|
||||||
{
|
{
|
||||||
|
|
||||||
SortPointer interfaceSort(ContractDefinition const& _contract)
|
SortPointer interfaceSort(ContractDefinition const& _contract, SymbolicState& _state)
|
||||||
{
|
{
|
||||||
return make_shared<FunctionSort>(
|
return make_shared<FunctionSort>(
|
||||||
stateSorts(_contract),
|
vector<SortPointer>{_state.thisAddressSort(), _state.stateSort()} + stateSorts(_contract),
|
||||||
SortProvider::boolSort
|
SortProvider::boolSort
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortPointer nondetInterfaceSort(ContractDefinition const& _contract)
|
SortPointer nondetInterfaceSort(ContractDefinition const& _contract, SymbolicState& _state)
|
||||||
{
|
{
|
||||||
auto varSorts = stateSorts(_contract);
|
auto varSorts = stateSorts(_contract);
|
||||||
|
vector<SortPointer> stateSort{_state.stateSort()};
|
||||||
return make_shared<FunctionSort>(
|
return make_shared<FunctionSort>(
|
||||||
varSorts + varSorts,
|
stateSort + varSorts + stateSort + varSorts,
|
||||||
SortProvider::boolSort
|
SortProvider::boolSort
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortPointer implicitConstructorSort()
|
SortPointer implicitConstructorSort(SymbolicState& _state)
|
||||||
{
|
{
|
||||||
return arity0FunctionSort();
|
return make_shared<FunctionSort>(
|
||||||
|
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.stateSort()},
|
||||||
|
SortProvider::boolSort
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortPointer constructorSort(ContractDefinition const& _contract)
|
SortPointer constructorSort(ContractDefinition const& _contract, SymbolicState& _state)
|
||||||
{
|
{
|
||||||
if (auto const* constructor = _contract.constructor())
|
if (auto const* constructor = _contract.constructor())
|
||||||
return functionSort(*constructor, &_contract);
|
return functionSort(*constructor, &_contract, _state);
|
||||||
|
|
||||||
return make_shared<FunctionSort>(
|
return make_shared<FunctionSort>(
|
||||||
vector<SortPointer>{SortProvider::uintSort} + stateSorts(_contract),
|
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.stateSort()} + stateSorts(_contract),
|
||||||
SortProvider::boolSort
|
SortProvider::boolSort
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition const* _contract)
|
SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state)
|
||||||
{
|
{
|
||||||
auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); };
|
auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); };
|
||||||
auto varSorts = _contract ? stateSorts(*_contract) : vector<SortPointer>{};
|
auto varSorts = _contract ? stateSorts(*_contract) : vector<SortPointer>{};
|
||||||
auto inputSorts = applyMap(_function.parameters(), smtSort);
|
auto inputSorts = applyMap(_function.parameters(), smtSort);
|
||||||
auto outputSorts = applyMap(_function.returnParameters(), smtSort);
|
auto outputSorts = applyMap(_function.returnParameters(), smtSort);
|
||||||
return make_shared<FunctionSort>(
|
return make_shared<FunctionSort>(
|
||||||
vector<SortPointer>{SortProvider::uintSort} +
|
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.stateSort()} +
|
||||||
varSorts +
|
varSorts +
|
||||||
inputSorts +
|
inputSorts +
|
||||||
|
vector<SortPointer>{_state.stateSort()} +
|
||||||
varSorts +
|
varSorts +
|
||||||
inputSorts +
|
inputSorts +
|
||||||
outputSorts,
|
outputSorts,
|
||||||
@ -78,9 +83,9 @@ SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefinition const* _contract)
|
SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state)
|
||||||
{
|
{
|
||||||
auto fSort = dynamic_pointer_cast<FunctionSort>(functionSort(_function, _contract));
|
auto fSort = dynamic_pointer_cast<FunctionSort>(functionSort(_function, _contract, _state));
|
||||||
solAssert(fSort, "");
|
solAssert(fSort, "");
|
||||||
|
|
||||||
auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); };
|
auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); };
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include <libsolidity/formal/Predicate.h>
|
#include <libsolidity/formal/Predicate.h>
|
||||||
|
|
||||||
|
#include <libsolidity/formal/SymbolicState.h>
|
||||||
|
|
||||||
#include <libsmtutil/Sorts.h>
|
#include <libsmtutil/Sorts.h>
|
||||||
|
|
||||||
namespace solidity::frontend::smt
|
namespace solidity::frontend::smt
|
||||||
@ -31,46 +33,46 @@ namespace solidity::frontend::smt
|
|||||||
*
|
*
|
||||||
* 1. Interface
|
* 1. Interface
|
||||||
* The idle state of a contract. Signature:
|
* The idle state of a contract. Signature:
|
||||||
* interface(stateVariables).
|
* interface(this, blockchainState, stateVariables).
|
||||||
*
|
*
|
||||||
* 2. Nondet interface
|
* 2. Nondet interface
|
||||||
* The nondeterminism behavior of a contract. Signature:
|
* The nondeterminism behavior of a contract. Signature:
|
||||||
* nondet_interface(stateVariables, stateVariables').
|
* nondet_interface(blockchainState, stateVariables, blockchainState', stateVariables').
|
||||||
*
|
*
|
||||||
* 3. Implicit constructor
|
* 3. Implicit constructor
|
||||||
* The implicit constructor of a contract, that is, without input parameters. Signature:
|
* The implicit constructor of a contract, that is, without input parameters. Signature:
|
||||||
* implicit_constructor().
|
* implicit_constructor(error, this, blockchainState).
|
||||||
*
|
*
|
||||||
* 4. Constructor entry/summary
|
* 4. Constructor entry/summary
|
||||||
* The summary of an implicit constructor. Signature:
|
* The summary of an implicit constructor. Signature:
|
||||||
* constructor_summary(error, stateVariables').
|
* constructor_summary(error, this, blockchainState, blockchainState', stateVariables').
|
||||||
*
|
*
|
||||||
* 5. Function entry/summary
|
* 5. Function entry/summary
|
||||||
* The entry point of a function definition. Signature:
|
* The entry point of a function definition. Signature:
|
||||||
* function_entry(error, stateVariables, inputVariables, stateVariables', inputVariables', outputVariables').
|
* function_entry(error, this, blockchainState, stateVariables, inputVariables, blockchainState', stateVariables', inputVariables', outputVariables').
|
||||||
*
|
*
|
||||||
* 6. Function body
|
* 6. Function body
|
||||||
* Use for any predicate within a function. Signature:
|
* Use for any predicate within a function. Signature:
|
||||||
* function_body(error, stateVariables, inputVariables, stateVariables', inputVariables', outputVariables', localVariables).
|
* function_body(error, this, blockchainState, stateVariables, inputVariables, blockchainState' ,stateVariables', inputVariables', outputVariables', localVariables).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// @returns the interface predicate sort for _contract.
|
/// @returns the interface predicate sort for _contract.
|
||||||
smtutil::SortPointer interfaceSort(ContractDefinition const& _contract);
|
smtutil::SortPointer interfaceSort(ContractDefinition const& _contract, SymbolicState& _state);
|
||||||
|
|
||||||
/// @returns the nondeterminisc interface predicate sort for _contract.
|
/// @returns the nondeterminisc interface predicate sort for _contract.
|
||||||
smtutil::SortPointer nondetInterfaceSort(ContractDefinition const& _contract);
|
smtutil::SortPointer nondetInterfaceSort(ContractDefinition const& _contract, SymbolicState& _state);
|
||||||
|
|
||||||
/// @returns the implicit constructor predicate sort.
|
/// @returns the implicit constructor predicate sort.
|
||||||
smtutil::SortPointer implicitConstructorSort();
|
smtutil::SortPointer implicitConstructorSort(SymbolicState& _state);
|
||||||
|
|
||||||
/// @returns the constructor entry/summary predicate sort for _contract.
|
/// @returns the constructor entry/summary predicate sort for _contract.
|
||||||
smtutil::SortPointer constructorSort(ContractDefinition const& _contract);
|
smtutil::SortPointer constructorSort(ContractDefinition const& _contract, SymbolicState& _state);
|
||||||
|
|
||||||
/// @returns the function entry/summary predicate sort for _function contained in _contract.
|
/// @returns the function entry/summary predicate sort for _function contained in _contract.
|
||||||
smtutil::SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition const* _contract);
|
smtutil::SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state);
|
||||||
|
|
||||||
/// @returns the function body predicate sort for _function contained in _contract.
|
/// @returns the function body predicate sort for _function contained in _contract.
|
||||||
smtutil::SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefinition const* _contract);
|
smtutil::SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state);
|
||||||
|
|
||||||
/// @returns the sort of a predicate without parameters.
|
/// @returns the sort of a predicate without parameters.
|
||||||
smtutil::SortPointer arity0FunctionSort();
|
smtutil::SortPointer arity0FunctionSort();
|
||||||
|
@ -2162,6 +2162,7 @@ void SMTEncoder::clearIndices(ContractDefinition const* _contract, FunctionDefin
|
|||||||
for (auto const& var: _function->localVariables())
|
for (auto const& var: _function->localVariables())
|
||||||
m_context.variable(*var)->resetIndex();
|
m_context.variable(*var)->resetIndex();
|
||||||
}
|
}
|
||||||
|
m_context.state().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression const* SMTEncoder::leftmostBase(IndexAccess const& _indexAccess)
|
Expression const* SMTEncoder::leftmostBase(IndexAccess const& _indexAccess)
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
// SPDX-License-Identifier: GPL-3.0
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
#include "libsmtutil/SolverInterface.h"
|
|
||||||
#include <libsolidity/formal/SymbolicState.h>
|
#include <libsolidity/formal/SymbolicState.h>
|
||||||
|
|
||||||
#include <libsolidity/formal/SymbolicTypes.h>
|
#include <libsolidity/formal/SymbolicTypes.h>
|
||||||
@ -56,11 +55,51 @@ void SymbolicState::reset()
|
|||||||
|
|
||||||
// Blockchain
|
// Blockchain
|
||||||
|
|
||||||
|
SymbolicIntVariable& SymbolicState::errorFlag()
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
SortPointer SymbolicState::errorFlagSort()
|
||||||
|
{
|
||||||
|
return m_error.sort();
|
||||||
|
}
|
||||||
|
|
||||||
smtutil::Expression SymbolicState::thisAddress()
|
smtutil::Expression SymbolicState::thisAddress()
|
||||||
{
|
{
|
||||||
return m_thisAddress.currentValue();
|
return m_thisAddress.currentValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smtutil::Expression SymbolicState::thisAddress(unsigned _idx)
|
||||||
|
{
|
||||||
|
return m_thisAddress.valueAtIndex(_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
SortPointer SymbolicState::thisAddressSort()
|
||||||
|
{
|
||||||
|
return m_thisAddress.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
smtutil::Expression SymbolicState::state()
|
||||||
|
{
|
||||||
|
return m_stateTuple->currentValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
smtutil::Expression SymbolicState::state(unsigned _idx)
|
||||||
|
{
|
||||||
|
return m_stateTuple->valueAtIndex(_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
SortPointer SymbolicState::stateSort()
|
||||||
|
{
|
||||||
|
return m_stateTuple->sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolicState::newState()
|
||||||
|
{
|
||||||
|
m_stateTuple->increaseIndex();
|
||||||
|
}
|
||||||
|
|
||||||
smtutil::Expression SymbolicState::balances()
|
smtutil::Expression SymbolicState::balances()
|
||||||
{
|
{
|
||||||
return m_stateTuple->component(m_componentIndices.at("balances"));
|
return m_stateTuple->component(m_componentIndices.at("balances"));
|
||||||
@ -76,21 +115,6 @@ smtutil::Expression SymbolicState::balance(smtutil::Expression _address)
|
|||||||
return smtutil::Expression::select(balances(), move(_address));
|
return smtutil::Expression::select(balances(), move(_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolicIntVariable& SymbolicState::errorFlag()
|
|
||||||
{
|
|
||||||
return m_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
smtutil::Expression SymbolicState::state()
|
|
||||||
{
|
|
||||||
return m_stateTuple->currentValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
SortPointer SymbolicState::stateSort()
|
|
||||||
{
|
|
||||||
return m_stateTuple->sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SymbolicState::transfer(smtutil::Expression _from, smtutil::Expression _to, smtutil::Expression _value)
|
void SymbolicState::transfer(smtutil::Expression _from, smtutil::Expression _to, smtutil::Expression _value)
|
||||||
{
|
{
|
||||||
unsigned indexBefore = m_stateTuple->index();
|
unsigned indexBefore = m_stateTuple->index();
|
||||||
|
@ -48,8 +48,20 @@ public:
|
|||||||
|
|
||||||
/// Blockchain.
|
/// Blockchain.
|
||||||
//@{
|
//@{
|
||||||
/// Value of `this` address.
|
SymbolicIntVariable& errorFlag();
|
||||||
|
smtutil::SortPointer errorFlagSort();
|
||||||
|
|
||||||
|
/// @returns the symbolic value of the currently executing contract's address.
|
||||||
smtutil::Expression thisAddress();
|
smtutil::Expression thisAddress();
|
||||||
|
smtutil::Expression thisAddress(unsigned _idx);
|
||||||
|
smtutil::SortPointer thisAddressSort();
|
||||||
|
|
||||||
|
/// @returns the state as a tuple.
|
||||||
|
smtutil::Expression state();
|
||||||
|
smtutil::Expression state(unsigned _idx);
|
||||||
|
smtutil::SortPointer stateSort();
|
||||||
|
void newState();
|
||||||
|
|
||||||
/// @returns the symbolic balances.
|
/// @returns the symbolic balances.
|
||||||
smtutil::Expression balances();
|
smtutil::Expression balances();
|
||||||
/// @returns the symbolic balance of address `this`.
|
/// @returns the symbolic balance of address `this`.
|
||||||
@ -57,14 +69,6 @@ public:
|
|||||||
/// @returns the symbolic balance of an address.
|
/// @returns the symbolic balance of an address.
|
||||||
smtutil::Expression balance(smtutil::Expression _address);
|
smtutil::Expression balance(smtutil::Expression _address);
|
||||||
|
|
||||||
SymbolicIntVariable& errorFlag();
|
|
||||||
|
|
||||||
/// @returns the state as a tuple.
|
|
||||||
smtutil::Expression state();
|
|
||||||
|
|
||||||
/// @returns the state sort.
|
|
||||||
smtutil::SortPointer stateSort();
|
|
||||||
|
|
||||||
/// Transfer _value from _from to _to.
|
/// Transfer _value from _from to _to.
|
||||||
void transfer(smtutil::Expression _from, smtutil::Expression _to, smtutil::Expression _value);
|
void transfer(smtutil::Expression _from, smtutil::Expression _to, smtutil::Expression _value);
|
||||||
//@}
|
//@}
|
||||||
|
@ -23,8 +23,6 @@ contract C {
|
|||||||
assert(s1[2].a[2] == s2.a[2]);
|
assert(s1[2].a[2] == s2.a[2]);
|
||||||
s1[0].ts[3].y = 5;
|
s1[0].ts[3].y = 5;
|
||||||
assert(s1[0].ts[3].y == s2.ts[3].y);
|
assert(s1[0].ts[3].y == s2.ts[3].y);
|
||||||
s1[1].ts[4].a[5] = 6;
|
|
||||||
assert(s1[1].ts[4].a[5] == s2.ts[4].a[5]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
|
Loading…
Reference in New Issue
Block a user