diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9a7fdc8bd..035262d5a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,7 +24,6 @@ detect_stray_source_files("${sources}" ".") set(contracts_sources contracts/AuctionRegistrar.cpp contracts/ContractInterface.h - contracts/FixedFeeRegistrar.cpp contracts/Wallet.cpp ) detect_stray_source_files("${contracts_sources}" "contracts/") diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp deleted file mode 100644 index b0f2ba8f6..000000000 --- a/test/contracts/FixedFeeRegistrar.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - This file is part of solidity. - - solidity 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. - - solidity 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 solidity. If not, see . -*/ -// SPDX-License-Identifier: GPL-3.0 -/** - * @author Christian - * @date 2015 - * Tests for a fixed fee registrar contract. - */ - -#include - -#include -#include -#include - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4535) // calling _set_se_translator requires /EHa -#endif -#include -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -#include - -using namespace std; -using namespace solidity; -using namespace solidity::util; -using namespace solidity::test; - -namespace solidity::frontend::test -{ - -namespace -{ - -static char const* registrarCode = R"DELIMITER( -//sol FixedFeeRegistrar -// Simple global registrar with fixed-fee reservations. -// @authors: -// Gav Wood - -pragma solidity >=0.4.0 <0.9.0; - -abstract contract Registrar { - event Changed(string indexed name); - - function owner(string memory _name) public virtual view returns (address o_owner); - function addr(string memory _name) public virtual view returns (address o_address); - function subRegistrar(string memory _name) virtual public view returns (address o_subRegistrar); - function content(string memory _name) public virtual view returns (bytes32 o_content); -} - -contract FixedFeeRegistrar is Registrar { - struct Record { - address addr; - address subRegistrar; - bytes32 content; - address owner; - } - - modifier onlyrecordowner(string memory _name) { if (m_record(_name).owner == msg.sender) _; } - - function reserve(string memory _name) public payable { - Record storage rec = m_record(_name); - if (rec.owner == 0x0000000000000000000000000000000000000000 && msg.value >= c_fee) { - rec.owner = msg.sender; - emit Changed(_name); - } - } - function disown(string memory _name, address payable _refund) onlyrecordowner(_name) public { - delete m_recordData[uint(keccak256(bytes(_name))) / 8]; - if (!_refund.send(c_fee)) - revert(); - emit Changed(_name); - } - function transfer(string memory _name, address _newOwner) onlyrecordowner(_name) public { - m_record(_name).owner = _newOwner; - emit Changed(_name); - } - function setAddr(string memory _name, address _a) onlyrecordowner(_name) public { - m_record(_name).addr = _a; - emit Changed(_name); - } - function setSubRegistrar(string memory _name, address _registrar) onlyrecordowner(_name) public { - m_record(_name).subRegistrar = _registrar; - emit Changed(_name); - } - function setContent(string memory _name, bytes32 _content) onlyrecordowner(_name) public { - m_record(_name).content = _content; - emit Changed(_name); - } - - function record(string memory _name) public view returns (address o_addr, address o_subRegistrar, bytes32 o_content, address o_owner) { - Record storage rec = m_record(_name); - o_addr = rec.addr; - o_subRegistrar = rec.subRegistrar; - o_content = rec.content; - o_owner = rec.owner; - } - function addr(string memory _name) public override view returns (address) { return m_record(_name).addr; } - function subRegistrar(string memory _name) public override view returns (address) { return m_record(_name).subRegistrar; } - function content(string memory _name) public override view returns (bytes32) { return m_record(_name).content; } - function owner(string memory _name) public override view returns (address) { return m_record(_name).owner; } - - Record[2**253] m_recordData; - function m_record(string memory _name) view internal returns (Record storage o_record) { - return m_recordData[uint(keccak256(bytes(_name))) / 8]; - } - uint constant c_fee = 69 ether; -} -)DELIMITER"; - -static LazyInit s_compiledRegistrar; - -class RegistrarTestFramework: public SolidityExecutionFramework -{ -protected: - void deployRegistrar() - { - bytes const& compiled = s_compiledRegistrar.init([&]{ - return compileContract(registrarCode, "FixedFeeRegistrar"); - }); - - sendMessage(compiled, true); - BOOST_REQUIRE(m_transactionSuccessful); - BOOST_REQUIRE(!m_output.empty()); - } - u256 const m_fee = u256("69000000000000000000"); -}; - -} - -/// This is a test suite that tests optimised code! -BOOST_FIXTURE_TEST_SUITE(SolidityFixedFeeRegistrar, RegistrarTestFramework) - -BOOST_AUTO_TEST_CASE(creation) -{ - deployRegistrar(); -} - -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()); - BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[0])) == encodeArgs(account(0))); - BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee + 1, encodeDyn(name[1])) == encodeArgs()); - BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[1])) == encodeArgs(account(0))); - BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee - 1, encodeDyn(name[2])) == encodeArgs()); - BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[2])) == encodeArgs(h160{})); -} - -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()); - BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(account(0))); - - sendEther(account(1), 100 * ether); - m_sender = account(1); - BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs()); - BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(account(0))); -} - -BOOST_AUTO_TEST_CASE(properties) -{ - // Test setting and retrieving the various properties works. - deployRegistrar(); - string names[] = {"abc", "def", "ghi"}; - size_t addr = 0x9872543; - size_t count = 1; - for (string const& name: names) - { - addr++; - m_sender = account(0); - sendEther(account(count), 100 * ether); - m_sender = account(count); - h160 owner = m_sender; - // setting by sender works - BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs()); - BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(owner)); - 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)); - count++; - // but not by someone else - m_sender = account(0); - sendEther(account(count), 100 * ether); - m_sender = account(count); - BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(owner)); - 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)); - count++; - } -} - -BOOST_AUTO_TEST_CASE(transfer) -{ - deployRegistrar(); - string name = "abc"; - BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs()); - BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), account(0), u256(name.length()), name) == encodeArgs()); - 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))); - BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(account(0))); -} - -BOOST_AUTO_TEST_CASE(disown) -{ - deployRegistrar(); - string name = "abc"; - BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs()); - BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), account(0), u256(name.length()), name) == encodeArgs()); - 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(h160(0x124)), 0); - BOOST_CHECK(callContractFunction("disown(string,address)", u256(0x40), u256(0x124), name.size(), name) == encodeArgs()); - BOOST_CHECK_EQUAL(balanceAt(h160(0x124)), m_fee); - - 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 diff --git a/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol new file mode 100644 index 000000000..b6d8f4399 --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/FixedFeeRegistrar.sol @@ -0,0 +1,111 @@ +//sol FixedFeeRegistrar +// Simple global registrar with fixed-fee reservations. +// @authors: +// Gav Wood + +pragma solidity >=0.4.0 <0.9.0; + +abstract contract Registrar { + event Changed(string indexed name); + + function owner(string memory _name) public virtual view returns (address o_owner); + function addr(string memory _name) public virtual view returns (address o_address); + function subRegistrar(string memory _name) virtual public view returns (address o_subRegistrar); + function content(string memory _name) public virtual view returns (bytes32 o_content); +} + +contract FixedFeeRegistrar is Registrar { + struct Record { + address addr; + address subRegistrar; + bytes32 content; + address owner; + } + + modifier onlyrecordowner(string memory _name) { if (m_record(_name).owner == msg.sender) _; } + + function reserve(string memory _name) public payable { + Record storage rec = m_record(_name); + if (rec.owner == 0x0000000000000000000000000000000000000000 && msg.value >= c_fee) { + rec.owner = msg.sender; + emit Changed(_name); + } + } + function disown(string memory _name, address payable _refund) onlyrecordowner(_name) public { + delete m_recordData[uint(keccak256(bytes(_name))) / 8]; + if (!_refund.send(c_fee)) + revert(); + emit Changed(_name); + } + function transfer(string memory _name, address _newOwner) onlyrecordowner(_name) public { + m_record(_name).owner = _newOwner; + emit Changed(_name); + } + function setAddr(string memory _name, address _a) onlyrecordowner(_name) public { + m_record(_name).addr = _a; + emit Changed(_name); + } + function setSubRegistrar(string memory _name, address _registrar) onlyrecordowner(_name) public { + m_record(_name).subRegistrar = _registrar; + emit Changed(_name); + } + function setContent(string memory _name, bytes32 _content) onlyrecordowner(_name) public { + m_record(_name).content = _content; + emit Changed(_name); + } + + function record(string memory _name) public view returns (address o_addr, address o_subRegistrar, bytes32 o_content, address o_owner) { + Record storage rec = m_record(_name); + o_addr = rec.addr; + o_subRegistrar = rec.subRegistrar; + o_content = rec.content; + o_owner = rec.owner; + } + function addr(string memory _name) public override view returns (address) { return m_record(_name).addr; } + function subRegistrar(string memory _name) public override view returns (address) { return m_record(_name).subRegistrar; } + function content(string memory _name) public override view returns (bytes32) { return m_record(_name).content; } + function owner(string memory _name) public override view returns (address) { return m_record(_name).owner; } + + Record[2**253] m_recordData; + function m_record(string memory _name) view internal returns (Record storage o_record) { + return m_recordData[uint(keccak256(bytes(_name))) / 8]; + } + uint constant c_fee = 69 ether; +} +// ==== +// compileViaYul: also +// ---- +// constructor() +// gas irOptimized: 544916 +// gas legacy: 942808 +// gas legacyOptimized: 492291 +// reserve(string), 69 ether: 0x20, 3, "abc" -> +// gas irOptimized: 45527 +// gas legacy: 46242 +// gas legacyOptimized: 45491 +// owner(string): 0x20, 3, "abc" -> 0x1212121212121212121212121212120000000012 +// reserve(string), 70 ether: 0x20, 3, "def" -> +// owner(string): 0x20, 3, "def" -> 0x1212121212121212121212121212120000000012 +// reserve(string), 68 ether: 0x20, 3, "ghi" -> +// owner(string): 0x20, 3, "ghi" -> 0 +// account: 1 -> 0x1212121212121212121212121212120000001012 +// reserve(string), 69 ether: 0x20, 3, "abc" -> +// owner(string): 0x20, 3, "abc" -> 0x1212121212121212121212121212120000000012 +// account: 0 -> 0x1212121212121212121212121212120000000012 +// setContent(string,bytes32): 0x40, 0, 3, "abc" -> +// transfer(string,address): 0x40, 555, 3, "abc" -> +// owner(string): 0x20, 3, "abc" -> 555 +// content(string): 0x20, 3, "abc" -> 0x00 +// setContent(string,bytes32): 0x40, 333, 3, "def" -> +// setAddr(string,address): 0x40, 124, 3, "def" -> +// setSubRegistrar(string,address): 0x40, 125, 3, "def" -> +// content(string): 0x20, 3, "def" -> 333 +// addr(string): 0x20, 3, "def" -> 124 +// subRegistrar(string): 0x20, 3, "def" -> 125 +// balance: 0x124 -> 0 +// disown(string,address): 0x40, 0x124, 3, "def" -> +// balance: 0x124 -> 0 +// owner(string): 0x20, 3, "def" -> 0 +// content(string): 0x20, 3, "def" -> 0 +// addr(string): 0x20, 3, "def" -> 0 +// subRegistrar(string): 0x20, 3, "def" -> 0