solidity/test/contracts/FixedFeeRegistrar.cpp

258 lines
10 KiB
C++
Raw Normal View History

2015-07-29 17:31:25 +00:00
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2015
* Tests for a fixed fee registrar contract.
*/
#include <string>
#include <tuple>
2016-03-18 08:22:15 +00:00
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4535) // calling _set_se_translator requires /EHa
#endif
2015-07-29 17:31:25 +00:00
#include <boost/test/unit_test.hpp>
2016-03-18 08:22:15 +00:00
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
2016-06-09 16:54:29 +00:00
#include <test/libsolidity/SolidityExecutionFramework.h>
2015-07-29 17:31:25 +00:00
using namespace std;
namespace dev
{
namespace solidity
{
namespace test
{
2015-08-04 14:31:27 +00:00
namespace
{
2015-07-29 17:31:25 +00:00
static char const* registrarCode = R"DELIMITER(
//sol FixedFeeRegistrar
// Simple global registrar with fixed-fee reservations.
// @authors:
// Gav Wood <g@ethdev.com>
2016-09-08 15:17:42 +00:00
pragma solidity ^0.4.0;
2016-08-19 17:57:21 +00:00
2015-07-29 17:31:25 +00:00
contract Registrar {
event Changed(string indexed name);
function owner(string _name) constant returns (address o_owner);
function addr(string _name) constant returns (address o_address);
function subRegistrar(string _name) constant returns (address o_subRegistrar);
function content(string _name) constant returns (bytes32 o_content);
}
contract FixedFeeRegistrar is Registrar {
struct Record {
address addr;
address subRegistrar;
bytes32 content;
address owner;
}
2016-09-05 12:54:50 +00:00
modifier onlyrecordowner(string _name) { if (m_record(_name).owner == msg.sender) _; }
2015-07-29 17:31:25 +00:00
function reserve(string _name) payable {
2015-07-29 17:31:25 +00:00
Record rec = m_record(_name);
if (rec.owner == 0 && msg.value >= c_fee) {
rec.owner = msg.sender;
Changed(_name);
}
}
function disown(string _name, address _refund) onlyrecordowner(_name) {
delete m_recordData[uint(sha3(_name)) / 8];
2016-06-28 22:14:22 +00:00
if (!_refund.send(c_fee))
throw;
2015-07-29 17:31:25 +00:00
Changed(_name);
}
function transfer(string _name, address _newOwner) onlyrecordowner(_name) {
m_record(_name).owner = _newOwner;
Changed(_name);
}
function setAddr(string _name, address _a) onlyrecordowner(_name) {
m_record(_name).addr = _a;
Changed(_name);
}
function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) {
m_record(_name).subRegistrar = _registrar;
Changed(_name);
}
function setContent(string _name, bytes32 _content) onlyrecordowner(_name) {
m_record(_name).content = _content;
Changed(_name);
}
function record(string _name) constant returns (address o_addr, address o_subRegistrar, bytes32 o_content, address o_owner) {
Record rec = m_record(_name);
o_addr = rec.addr;
o_subRegistrar = rec.subRegistrar;
o_content = rec.content;
o_owner = rec.owner;
}
function addr(string _name) constant returns (address) { return m_record(_name).addr; }
function subRegistrar(string _name) constant returns (address) { return m_record(_name).subRegistrar; }
function content(string _name) constant returns (bytes32) { return m_record(_name).content; }
function owner(string _name) constant returns (address) { return m_record(_name).owner; }
Record[2**253] m_recordData;
function m_record(string _name) constant internal returns (Record storage o_record) {
return m_recordData[uint(sha3(_name)) / 8];
}
uint constant c_fee = 69 ether;
}
)DELIMITER";
static unique_ptr<bytes> s_compiledRegistrar;
class RegistrarTestFramework: public ExecutionFramework
{
protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
{
m_optimize = true;
2016-08-15 14:58:01 +00:00
m_compiler.reset(false);
2015-07-29 17:31:25 +00:00
m_compiler.addSource("", registrarCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
s_compiledRegistrar.reset(new bytes(m_compiler.object("FixedFeeRegistrar").bytecode));
2015-07-29 17:31:25 +00:00
}
sendMessage(*s_compiledRegistrar, true);
2016-06-28 21:57:02 +00:00
BOOST_REQUIRE(!m_output.empty());
2015-07-29 17:31:25 +00:00
}
u256 const m_fee = u256("69000000000000000000");
};
2015-08-04 14:31:27 +00:00
}
2015-07-29 17:31:25 +00:00
/// This is a test suite that tests optimised code!
BOOST_FIXTURE_TEST_SUITE(SolidityFixedFeeRegistrar, RegistrarTestFramework)
BOOST_AUTO_TEST_CASE(creation)
{
2016-06-28 21:57:02 +00:00
deployRegistrar();
2015-07-29 17:31:25 +00:00
}
BOOST_AUTO_TEST_CASE(reserve)
{
// Test that reserving works and fee is taken into account.
deployRegistrar();
string name[] = {"abc", "def", "ghi"};
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name[0])) == encodeArgs());
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[0])) == encodeArgs(h256(account(0), h256::AlignRight)));
2015-07-29 17:31:25 +00:00
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee + 1, encodeDyn(name[1])) == encodeArgs());
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[1])) == encodeArgs(h256(account(0), h256::AlignRight)));
2015-07-29 17:31:25 +00:00
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee - 1, encodeDyn(name[2])) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[2])) == encodeArgs(h256(0)));
}
BOOST_AUTO_TEST_CASE(double_reserve)
{
// Test that it is not possible to re-reserve from a different address.
deployRegistrar();
string name = "abc";
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(account(0), h256::AlignRight)));
2015-07-29 17:31:25 +00:00
Make the Solidity repository standalone. This commit is the culmination of several months of work to decouple Solidity from the webthree-umbrella so that it can be developed in parallel with cpp-ethereum (the Ethereum C++ runtime) and so that even for the Solidity unit-tests there is no hard-dependency onto the C++ runtime. The Tests-over-IPC refactoring was a major step in the same process which was already committed. This commit contains the following changes: - A subset of the CMake functionality in webthree-helpers was extracted and tailored for Solidity into ./cmake. Further cleanup is certainly possible. - A subset of the libdevcore functionality in libweb3core was extracted and tailored for Solidity into ./libdevcore. Further cleanup is certainly possible - The gas price constants in EVMSchedule were orphaned into libevmasm. - Some other refactorings and cleanups were made to sever unnecessary EVM dependencies in the Solidity unit-tests. - TravisCI and Appveyor support was added, covering builds and running of the unit-tests (Linux and macOS only for now) - A bug-fix was made to get the Tests-over-IPC running on macOS. - There are still reliability issues in the unit-tests, which need immediate attention. The Travis build has been flipped to run the unit-tests 5 times, to try to flush these out. - The Emscripten automation which was previously in webthree-umbrella was merged into the TravisCI automation here. - The development ZIP deployment step has been commented out, but we will want to read that ONLY for release branch. Further iteration on these changes will definitely be needed, but I feel these have got to sufficient maturity than holding them back further isn't winning us anything. It is go time :-)
2016-08-01 05:25:37 +00:00
sendEther(account(1), 100 * ether);
2016-06-18 00:08:20 +00:00
m_sender = account(1);
2015-07-29 17:31:25 +00:00
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(account(0), h256::AlignRight)));
2015-07-29 17:31:25 +00:00
}
BOOST_AUTO_TEST_CASE(properties)
{
// Test setting and retrieving the various properties works.
deployRegistrar();
string names[] = {"abc", "def", "ghi"};
size_t addr = 0x9872543;
2016-06-18 00:08:20 +00:00
size_t count = 1;
2015-07-29 17:31:25 +00:00
for (string const& name: names)
{
addr++;
2016-06-18 00:08:20 +00:00
m_sender = account(0);
Make the Solidity repository standalone. This commit is the culmination of several months of work to decouple Solidity from the webthree-umbrella so that it can be developed in parallel with cpp-ethereum (the Ethereum C++ runtime) and so that even for the Solidity unit-tests there is no hard-dependency onto the C++ runtime. The Tests-over-IPC refactoring was a major step in the same process which was already committed. This commit contains the following changes: - A subset of the CMake functionality in webthree-helpers was extracted and tailored for Solidity into ./cmake. Further cleanup is certainly possible. - A subset of the libdevcore functionality in libweb3core was extracted and tailored for Solidity into ./libdevcore. Further cleanup is certainly possible - The gas price constants in EVMSchedule were orphaned into libevmasm. - Some other refactorings and cleanups were made to sever unnecessary EVM dependencies in the Solidity unit-tests. - TravisCI and Appveyor support was added, covering builds and running of the unit-tests (Linux and macOS only for now) - A bug-fix was made to get the Tests-over-IPC running on macOS. - There are still reliability issues in the unit-tests, which need immediate attention. The Travis build has been flipped to run the unit-tests 5 times, to try to flush these out. - The Emscripten automation which was previously in webthree-umbrella was merged into the TravisCI automation here. - The development ZIP deployment step has been commented out, but we will want to read that ONLY for release branch. Further iteration on these changes will definitely be needed, but I feel these have got to sufficient maturity than holding them back further isn't winning us anything. It is go time :-)
2016-08-01 05:25:37 +00:00
sendEther(account(count), 100 * ether);
2016-06-18 00:08:20 +00:00
m_sender = account(count);
Address owner = m_sender;
2015-07-29 17:31:25 +00:00
// setting by sender works
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(owner, h256::AlignRight)));
2015-07-29 17:31:25 +00:00
BOOST_CHECK(callContractFunction("setAddr(string,address)", u256(0x40), u256(addr), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("addr(string)", encodeDyn(name)) == encodeArgs(addr));
BOOST_CHECK(callContractFunction("setSubRegistrar(string,address)", u256(0x40), addr + 20, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("subRegistrar(string)", encodeDyn(name)) == encodeArgs(addr + 20));
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), addr + 90, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(addr + 90));
2016-06-18 00:08:20 +00:00
count++;
2015-07-29 17:31:25 +00:00
// but not by someone else
2016-06-20 23:39:06 +00:00
m_sender = account(0);
Make the Solidity repository standalone. This commit is the culmination of several months of work to decouple Solidity from the webthree-umbrella so that it can be developed in parallel with cpp-ethereum (the Ethereum C++ runtime) and so that even for the Solidity unit-tests there is no hard-dependency onto the C++ runtime. The Tests-over-IPC refactoring was a major step in the same process which was already committed. This commit contains the following changes: - A subset of the CMake functionality in webthree-helpers was extracted and tailored for Solidity into ./cmake. Further cleanup is certainly possible. - A subset of the libdevcore functionality in libweb3core was extracted and tailored for Solidity into ./libdevcore. Further cleanup is certainly possible - The gas price constants in EVMSchedule were orphaned into libevmasm. - Some other refactorings and cleanups were made to sever unnecessary EVM dependencies in the Solidity unit-tests. - TravisCI and Appveyor support was added, covering builds and running of the unit-tests (Linux and macOS only for now) - A bug-fix was made to get the Tests-over-IPC running on macOS. - There are still reliability issues in the unit-tests, which need immediate attention. The Travis build has been flipped to run the unit-tests 5 times, to try to flush these out. - The Emscripten automation which was previously in webthree-umbrella was merged into the TravisCI automation here. - The development ZIP deployment step has been commented out, but we will want to read that ONLY for release branch. Further iteration on these changes will definitely be needed, but I feel these have got to sufficient maturity than holding them back further isn't winning us anything. It is go time :-)
2016-08-01 05:25:37 +00:00
sendEther(account(count), 100 * ether);
2016-06-18 00:08:20 +00:00
m_sender = account(count);
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(owner, h256::AlignRight)));
2015-07-29 17:31:25 +00:00
BOOST_CHECK(callContractFunction("setAddr(string,address)", u256(0x40), addr + 1, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("addr(string)", encodeDyn(name)) == encodeArgs(addr));
BOOST_CHECK(callContractFunction("setSubRegistrar(string,address)", u256(0x40), addr + 20 + 1, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("subRegistrar(string)", encodeDyn(name)) == encodeArgs(addr + 20));
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), addr + 90 + 1, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(addr + 90));
2016-06-18 00:08:20 +00:00
count++;
2015-07-29 17:31:25 +00:00
}
}
BOOST_AUTO_TEST_CASE(transfer)
{
deployRegistrar();
string name = "abc";
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), h256(account(0), h256::AlignRight), u256(name.length()), name) == encodeArgs());
2015-07-29 17:31:25 +00:00
BOOST_CHECK(callContractFunction("transfer(string,address)", u256(0x40), u256(555), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(u256(555)));
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(h256(account(0), h256::AlignRight)));
2015-07-29 17:31:25 +00:00
}
BOOST_AUTO_TEST_CASE(disown)
{
deployRegistrar();
string name = "abc";
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
2016-06-18 00:08:20 +00:00
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), h256(account(0), h256::AlignRight), u256(name.length()), name) == encodeArgs());
2015-07-29 17:31:25 +00:00
BOOST_CHECK(callContractFunction("setAddr(string,address)", u256(0x40), u256(124), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("setSubRegistrar(string,address)", u256(0x40), u256(125), u256(name.length()), name) == encodeArgs());
BOOST_CHECK_EQUAL(balanceAt(Address(0x124)), 0);
2015-07-29 17:31:25 +00:00
BOOST_CHECK(callContractFunction("disown(string,address)", u256(0x40), u256(0x124), name.size(), name) == encodeArgs());
BOOST_CHECK_EQUAL(balanceAt(Address(0x124)), m_fee);
2015-07-29 17:31:25 +00:00
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(u256(0)));
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(u256(0)));
BOOST_CHECK(callContractFunction("addr(string)", encodeDyn(name)) == encodeArgs(u256(0)));
BOOST_CHECK(callContractFunction("subRegistrar(string)", encodeDyn(name)) == encodeArgs(u256(0)));
}
BOOST_AUTO_TEST_SUITE_END()
}
}
} // end namespaces