aboutsummaryrefslogtreecommitdiffstats
path: root/test/contracts
diff options
context:
space:
mode:
Diffstat (limited to 'test/contracts')
-rw-r--r--test/contracts/AuctionRegistrar.cpp101
-rw-r--r--test/contracts/FixedFeeRegistrar.cpp59
-rw-r--r--test/contracts/LLL_ENS.cpp3
-rw-r--r--test/contracts/LLL_ERC20.cpp7
-rw-r--r--test/contracts/Wallet.cpp62
5 files changed, 121 insertions, 111 deletions
diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp
index 5e4991e2..70503605 100644
--- a/test/contracts/AuctionRegistrar.cpp
+++ b/test/contracts/AuctionRegistrar.cpp
@@ -43,20 +43,20 @@ static char const* registrarCode = R"DELIMITER(
pragma solidity ^0.4.0;
contract NameRegister {
- function addr(string _name) constant returns (address o_owner);
- function name(address _owner) constant returns (string o_name);
+ function addr(string memory _name) public view returns (address o_owner);
+ function name(address _owner) public view returns (string memory o_name);
}
contract Registrar is NameRegister {
event Changed(string indexed name);
event PrimaryChanged(string indexed name, address indexed addr);
- 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);
+ function owner(string memory _name) public view returns (address o_owner);
+ function addr(string memory _name) public view returns (address o_address);
+ function subRegistrar(string memory _name) public view returns (address o_subRegistrar);
+ function content(string memory _name) public view returns (bytes32 o_content);
- function name(address _owner) constant returns (string o_name);
+ function name(address _owner) public view returns (string memory o_name);
}
contract AuctionSystem {
@@ -64,13 +64,13 @@ contract AuctionSystem {
event NewBid(string indexed _name, address _bidder, uint _value);
/// Function that is called once an auction ends.
- function onAuctionEnd(string _name) internal;
+ function onAuctionEnd(string memory _name) internal;
- function bid(string _name, address _bidder, uint _value) internal {
- var auction = m_auctions[_name];
+ function bid(string memory _name, address payable _bidder, uint _value) internal {
+ Auction storage auction = m_auctions[_name];
if (auction.endDate > 0 && now > auction.endDate)
{
- AuctionEnded(_name, auction.highestBidder);
+ emit AuctionEnded(_name, auction.highestBidder);
onAuctionEnd(_name);
delete m_auctions[_name];
return;
@@ -84,14 +84,14 @@ contract AuctionSystem {
auction.highestBidder = _bidder;
auction.endDate = now + c_biddingTime;
- NewBid(_name, _bidder, _value);
+ emit NewBid(_name, _bidder, _value);
}
}
uint constant c_biddingTime = 7 days;
struct Auction {
- address highestBidder;
+ address payable highestBidder;
uint highestBid;
uint secondHighestBid;
uint sumOfBids;
@@ -102,91 +102,91 @@ contract AuctionSystem {
contract GlobalRegistrar is Registrar, AuctionSystem {
struct Record {
- address owner;
+ address payable owner;
address primary;
address subRegistrar;
bytes32 content;
uint renewalDate;
}
- uint constant c_renewalInterval = 1 years;
+ uint constant c_renewalInterval = 365 days;
uint constant c_freeBytes = 12;
- function Registrar() {
+ function Registrar() public {
// TODO: Populate with hall-of-fame.
}
- function onAuctionEnd(string _name) internal {
- var auction = m_auctions[_name];
- var record = m_toRecord[_name];
- var previousOwner = record.owner;
+ function onAuctionEnd(string memory _name) internal {
+ Auction storage auction = m_auctions[_name];
+ Record storage record = m_toRecord[_name];
+ address previousOwner = record.owner;
record.renewalDate = now + c_renewalInterval;
record.owner = auction.highestBidder;
- Changed(_name);
- if (previousOwner != 0) {
+ emit Changed(_name);
+ if (previousOwner != 0x0000000000000000000000000000000000000000) {
if (!record.owner.send(auction.sumOfBids - auction.highestBid / 100))
- throw;
+ revert();
} else {
if (!auction.highestBidder.send(auction.highestBid - auction.secondHighestBid))
- throw;
+ revert();
}
}
- function reserve(string _name) external payable {
+ function reserve(string calldata _name) external payable {
if (bytes(_name).length == 0)
- throw;
+ revert();
bool needAuction = requiresAuction(_name);
if (needAuction)
{
if (now < m_toRecord[_name].renewalDate)
- throw;
+ revert();
bid(_name, msg.sender, msg.value);
} else {
- Record record = m_toRecord[_name];
- if (record.owner != 0)
- throw;
+ Record storage record = m_toRecord[_name];
+ if (record.owner != 0x0000000000000000000000000000000000000000)
+ revert();
m_toRecord[_name].owner = msg.sender;
- Changed(_name);
+ emit Changed(_name);
}
}
- function requiresAuction(string _name) internal returns (bool) {
+ function requiresAuction(string memory _name) internal returns (bool) {
return bytes(_name).length < c_freeBytes;
}
- modifier onlyrecordowner(string _name) { if (m_toRecord[_name].owner == msg.sender) _; }
+ modifier onlyrecordowner(string memory _name) { if (m_toRecord[_name].owner == msg.sender) _; }
- function transfer(string _name, address _newOwner) onlyrecordowner(_name) {
+ function transfer(string memory _name, address payable _newOwner) onlyrecordowner(_name) public {
m_toRecord[_name].owner = _newOwner;
- Changed(_name);
+ emit Changed(_name);
}
- function disown(string _name) onlyrecordowner(_name) {
+ function disown(string memory _name) onlyrecordowner(_name) public {
if (stringsEqual(m_toName[m_toRecord[_name].primary], _name))
{
- PrimaryChanged(_name, m_toRecord[_name].primary);
+ emit PrimaryChanged(_name, m_toRecord[_name].primary);
m_toName[m_toRecord[_name].primary] = "";
}
delete m_toRecord[_name];
- Changed(_name);
+ emit Changed(_name);
}
- function setAddress(string _name, address _a, bool _primary) onlyrecordowner(_name) {
+ function setAddress(string memory _name, address _a, bool _primary) onlyrecordowner(_name) public {
m_toRecord[_name].primary = _a;
if (_primary)
{
- PrimaryChanged(_name, _a);
+ emit PrimaryChanged(_name, _a);
m_toName[_a] = _name;
}
- Changed(_name);
+ emit Changed(_name);
}
- function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) {
+ function setSubRegistrar(string memory _name, address _registrar) onlyrecordowner(_name) public {
m_toRecord[_name].subRegistrar = _registrar;
- Changed(_name);
+ emit Changed(_name);
}
- function setContent(string _name, bytes32 _content) onlyrecordowner(_name) {
+ function setContent(string memory _name, bytes32 _content) onlyrecordowner(_name) public {
m_toRecord[_name].content = _content;
- Changed(_name);
+ emit Changed(_name);
}
function stringsEqual(string storage _a, string memory _b) internal returns (bool) {
@@ -201,11 +201,11 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
return true;
}
- function owner(string _name) constant returns (address) { return m_toRecord[_name].owner; }
- function addr(string _name) constant returns (address) { return m_toRecord[_name].primary; }
- function subRegistrar(string _name) constant returns (address) { return m_toRecord[_name].subRegistrar; }
- function content(string _name) constant returns (bytes32) { return m_toRecord[_name].content; }
- function name(address _addr) constant returns (string o_name) { return m_toName[_addr]; }
+ function owner(string memory _name) public view returns (address) { return m_toRecord[_name].owner; }
+ function addr(string memory _name) public view returns (address) { return m_toRecord[_name].primary; }
+ function subRegistrar(string memory _name) public view returns (address) { return m_toRecord[_name].subRegistrar; }
+ function content(string memory _name) public view returns (bytes32) { return m_toRecord[_name].content; }
+ function name(address _addr) public view returns (string memory o_name) { return m_toName[_addr]; }
mapping (address => string) m_toName;
mapping (string => Record) m_toRecord;
@@ -223,6 +223,7 @@ protected:
s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "GlobalRegistrar")));
sendMessage(*s_compiledRegistrar, true);
+ BOOST_REQUIRE(m_transactionSuccessful);
BOOST_REQUIRE(!m_output.empty());
}
diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp
index a3a27c37..ae921a96 100644
--- a/test/contracts/FixedFeeRegistrar.cpp
+++ b/test/contracts/FixedFeeRegistrar.cpp
@@ -58,10 +58,10 @@ pragma solidity ^0.4.0;
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);
+ function owner(string memory _name) public view returns (address o_owner);
+ function addr(string memory _name) public view returns (address o_address);
+ function subRegistrar(string memory _name) public view returns (address o_subRegistrar);
+ function content(string memory _name) public view returns (bytes32 o_content);
}
contract FixedFeeRegistrar is Registrar {
@@ -72,53 +72,53 @@ contract FixedFeeRegistrar is Registrar {
address owner;
}
- modifier onlyrecordowner(string _name) { if (m_record(_name).owner == msg.sender) _; }
+ modifier onlyrecordowner(string memory _name) { if (m_record(_name).owner == msg.sender) _; }
- function reserve(string _name) payable {
- Record rec = m_record(_name);
- if (rec.owner == 0 && msg.value >= c_fee) {
+ 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;
- Changed(_name);
+ emit Changed(_name);
}
}
- function disown(string _name, address _refund) onlyrecordowner(_name) {
- delete m_recordData[uint(keccak256(_name)) / 8];
+ function disown(string memory _name, address payable _refund) onlyrecordowner(_name) public {
+ delete m_recordData[uint(keccak256(bytes(_name))) / 8];
if (!_refund.send(c_fee))
- throw;
- Changed(_name);
+ revert();
+ emit Changed(_name);
}
- function transfer(string _name, address _newOwner) onlyrecordowner(_name) {
+ function transfer(string memory _name, address _newOwner) onlyrecordowner(_name) public {
m_record(_name).owner = _newOwner;
- Changed(_name);
+ emit Changed(_name);
}
- function setAddr(string _name, address _a) onlyrecordowner(_name) {
+ function setAddr(string memory _name, address _a) onlyrecordowner(_name) public {
m_record(_name).addr = _a;
- Changed(_name);
+ emit Changed(_name);
}
- function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) {
+ function setSubRegistrar(string memory _name, address _registrar) onlyrecordowner(_name) public {
m_record(_name).subRegistrar = _registrar;
- Changed(_name);
+ emit Changed(_name);
}
- function setContent(string _name, bytes32 _content) onlyrecordowner(_name) {
+ function setContent(string memory _name, bytes32 _content) onlyrecordowner(_name) public {
m_record(_name).content = _content;
- Changed(_name);
+ emit 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);
+ 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 _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; }
+ function addr(string memory _name) public view returns (address) { return m_record(_name).addr; }
+ function subRegistrar(string memory _name) public view returns (address) { return m_record(_name).subRegistrar; }
+ function content(string memory _name) public view returns (bytes32) { return m_record(_name).content; }
+ function owner(string memory _name) public view 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(keccak256(_name)) / 8];
+ 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;
}
@@ -135,6 +135,7 @@ protected:
s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "FixedFeeRegistrar")));
sendMessage(*s_compiledRegistrar, true);
+ BOOST_REQUIRE(m_transactionSuccessful);
BOOST_REQUIRE(!m_output.empty());
}
u256 const m_fee = u256("69000000000000000000");
diff --git a/test/contracts/LLL_ENS.cpp b/test/contracts/LLL_ENS.cpp
index 028d58c8..cfd6970c 100644
--- a/test/contracts/LLL_ENS.cpp
+++ b/test/contracts/LLL_ENS.cpp
@@ -28,7 +28,7 @@
#define ACCOUNT(n) h256(account(n), h256::AlignRight)
using namespace std;
-using namespace dev::eth;
+using namespace dev::lll;
namespace dev
{
@@ -349,6 +349,7 @@ protected:
BOOST_REQUIRE(errors.empty());
}
sendMessage(*s_compiledEns, true);
+ BOOST_REQUIRE(m_transactionSuccessful);
BOOST_REQUIRE(!m_output.empty());
}
diff --git a/test/contracts/LLL_ERC20.cpp b/test/contracts/LLL_ERC20.cpp
index 60b43e4f..6c6762dd 100644
--- a/test/contracts/LLL_ERC20.cpp
+++ b/test/contracts/LLL_ERC20.cpp
@@ -33,7 +33,7 @@
#define SUCCESS encodeArgs(1)
using namespace std;
-using namespace dev::eth;
+using namespace dev::lll;
namespace dev
{
@@ -400,6 +400,7 @@ protected:
BOOST_REQUIRE(errors.empty());
}
sendMessage(*s_compiledErc20, true);
+ BOOST_REQUIRE(m_transactionSuccessful);
BOOST_REQUIRE(!m_output.empty());
}
@@ -629,18 +630,22 @@ BOOST_AUTO_TEST_CASE(bad_data)
// Correct data: transfer(address _to, 1).
sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a123456789a") + encodeArgs(1), false, 0);
+ BOOST_CHECK(m_transactionSuccessful);
BOOST_CHECK(m_output == SUCCESS);
// Too little data (address is truncated by one byte).
sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a12345678") + encodeArgs(1), false, 0);
+ BOOST_CHECK(!m_transactionSuccessful);
BOOST_CHECK(m_output != SUCCESS);
// Too much data (address is extended with a zero byte).
sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a123456789a00") + encodeArgs(1), false, 0);
+ BOOST_CHECK(!m_transactionSuccessful);
BOOST_CHECK(m_output != SUCCESS);
// Invalid address (a bit above the 160th is set).
sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000100123456789a123456789a123456789a123456789a") + encodeArgs(1), false, 0);
+ BOOST_CHECK(!m_transactionSuccessful);
BOOST_CHECK(m_output != SUCCESS);
}
diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp
index 1031e8f1..e0e3045c 100644
--- a/test/contracts/Wallet.cpp
+++ b/test/contracts/Wallet.cpp
@@ -101,7 +101,7 @@ contract multiowned {
// constructor is given number of sigs required to do protected "onlymanyowners" transactions
// as well as the selection of addresses capable of confirming them.
- function multiowned(address[] _owners, uint _required) {
+ constructor(address[] memory _owners, uint _required) public {
m_numOwners = _owners.length + 1;
m_owners[1] = uint(msg.sender);
m_ownerIndex[uint(msg.sender)] = 1;
@@ -119,11 +119,11 @@ contract multiowned {
// make sure they're an owner
if (ownerIndex == 0) return;
uint ownerIndexBit = 2**ownerIndex;
- var pending = m_pending[_operation];
+ PendingState storage pending = m_pending[_operation];
if (pending.ownersDone & ownerIndexBit > 0) {
pending.yetNeeded++;
pending.ownersDone -= ownerIndexBit;
- Revoke(msg.sender, _operation);
+ emit Revoke(msg.sender, _operation);
}
}
@@ -137,7 +137,7 @@ contract multiowned {
m_owners[ownerIndex] = uint(_to);
m_ownerIndex[uint(_from)] = 0;
m_ownerIndex[uint(_to)] = ownerIndex;
- OwnerChanged(_from, _to);
+ emit OwnerChanged(_from, _to);
}
function addOwner(address _owner) onlymanyowners(keccak256(msg.data)) external {
@@ -151,7 +151,7 @@ contract multiowned {
m_numOwners++;
m_owners[m_numOwners] = uint(_owner);
m_ownerIndex[uint(_owner)] = m_numOwners;
- OwnerAdded(_owner);
+ emit OwnerAdded(_owner);
}
function removeOwner(address _owner) onlymanyowners(keccak256(msg.data)) external {
@@ -163,22 +163,22 @@ contract multiowned {
m_ownerIndex[uint(_owner)] = 0;
clearPending();
reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot
- OwnerRemoved(_owner);
+ emit OwnerRemoved(_owner);
}
function changeRequirement(uint _newRequired) onlymanyowners(keccak256(msg.data)) external {
if (_newRequired > m_numOwners) return;
m_required = _newRequired;
clearPending();
- RequirementChanged(_newRequired);
+ emit RequirementChanged(_newRequired);
}
- function isOwner(address _addr) returns (bool) {
+ function isOwner(address _addr) public returns (bool) {
return m_ownerIndex[uint(_addr)] > 0;
}
- function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) {
- var pending = m_pending[_operation];
+ function hasConfirmed(bytes32 _operation, address _owner) public view returns (bool) {
+ PendingState storage pending = m_pending[_operation];
uint ownerIndex = m_ownerIndex[uint(_owner)];
// make sure they're an owner
@@ -199,9 +199,9 @@ contract multiowned {
// determine what index the present sender is:
uint ownerIndex = m_ownerIndex[uint(msg.sender)];
// make sure they're an owner
- if (ownerIndex == 0) return;
+ if (ownerIndex == 0) return false;
- var pending = m_pending[_operation];
+ PendingState storage pending = m_pending[_operation];
// if we're not yet working on this operation, switch over and reset the confirmation status.
if (pending.yetNeeded == 0) {
// reset count of confirmations needed.
@@ -215,7 +215,7 @@ contract multiowned {
uint ownerIndexBit = 2**ownerIndex;
// make sure we (the message sender) haven't confirmed this operation previously.
if (pending.ownersDone & ownerIndexBit == 0) {
- Confirmation(msg.sender, _operation);
+ emit Confirmation(msg.sender, _operation);
// ok - check if count is enough to go ahead.
if (pending.yetNeeded <= 1) {
// enough confirmations: reset and run interior.
@@ -228,6 +228,7 @@ contract multiowned {
// not enough: record that this owner in particular confirmed.
pending.yetNeeded--;
pending.ownersDone |= ownerIndexBit;
+ return false;
}
}
}
@@ -288,7 +289,7 @@ contract daylimit is multiowned {
// METHODS
// constructor - stores initial daily limit and records the present day's index.
- function daylimit(uint _limit) {
+ constructor(uint _limit) public {
m_dailyLimit = _limit;
m_lastDay = today();
}
@@ -319,7 +320,7 @@ contract daylimit is multiowned {
return false;
}
// determines today's index.
- function today() private constant returns (uint) { return now / 1 days; }
+ function today() private view returns (uint) { return now / 1 days; }
// FIELDS
@@ -347,8 +348,8 @@ contract multisig {
// TODO: document
function changeOwner(address _from, address _to) external;
- function execute(address _to, uint _value, bytes _data) external returns (bytes32);
- function confirm(bytes32 _h) returns (bool);
+ function execute(address _to, uint _value, bytes calldata _data) external returns (bytes32);
+ function confirm(bytes32 _h) public returns (bool);
}
// usage:
@@ -369,50 +370,50 @@ contract Wallet is multisig, multiowned, daylimit {
// constructor - just pass on the owner array to the multiowned and
// the limit to daylimit
- function Wallet(address[] _owners, uint _required, uint _daylimit) payable
+ constructor(address[] memory _owners, uint _required, uint _daylimit) public payable
multiowned(_owners, _required) daylimit(_daylimit) {
}
// destroys the contract sending everything to `_to`.
- function kill(address _to) onlymanyowners(keccak256(msg.data)) external {
+ function kill(address payable _to) onlymanyowners(keccak256(msg.data)) external {
selfdestruct(_to);
}
// gets called when no other function matches
- function() payable {
+ function() external payable {
// just being sent some cash?
if (msg.value > 0)
- Deposit(msg.sender, msg.value);
+ emit Deposit(msg.sender, msg.value);
}
- // Outside-visible transact entry point. Executes transacion immediately if below daily spend limit.
+ // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit.
// If not, goes into multisig process. We provide a hash on return to allow the sender to provide
// shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
// and _data arguments). They still get the option of using them if they want, anyways.
- function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 _r) {
+ function execute(address _to, uint _value, bytes calldata _data) external onlyowner returns (bytes32 _r) {
// first, take the opportunity to check that we're under the daily limit.
if (underLimit(_value)) {
- SingleTransact(msg.sender, _value, _to, _data);
+ emit SingleTransact(msg.sender, _value, _to, _data);
// yes - just execute the call.
_to.call.value(_value)(_data);
return 0;
}
// determine our operation hash.
- _r = keccak256(msg.data, block.number);
- if (!confirm(_r) && m_txs[_r].to == 0) {
+ _r = keccak256(abi.encodePacked(msg.data, block.number));
+ if (!confirm(_r) && m_txs[_r].to == 0x0000000000000000000000000000000000000000) {
m_txs[_r].to = _to;
m_txs[_r].value = _value;
m_txs[_r].data = _data;
- ConfirmationNeeded(_r, msg.sender, _value, _to, _data);
+ emit ConfirmationNeeded(_r, msg.sender, _value, _to, _data);
}
}
// confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order
// to determine the body of the transaction from the hash provided.
- function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) {
- if (m_txs[_h].to != 0) {
+ function confirm(bytes32 _h) onlymanyowners(_h) public returns (bool) {
+ if (m_txs[_h].to != 0x0000000000000000000000000000000000000000) {
m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data);
- MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data);
+ emit MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data);
delete m_txs[_h];
return true;
}
@@ -451,6 +452,7 @@ protected:
bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners);
sendMessage(*s_compiledWallet + args, true, _value);
+ BOOST_REQUIRE(m_transactionSuccessful);
BOOST_REQUIRE(!m_output.empty());
}
};