Doc update.

Doc update.

// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a
// single, or, crucially, each of a number of, designated owners.
// usage:
// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by
// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
// interior is executed.
contract multiowned {
	// struct for the status of a pending operation.
	struct PendingState {
		uint yetNeeded;
		uint ownersDone;
	}

	// this contract only has two types of events: it can accept a confirmation, in which case
	// we record owner and operation (hash) alongside it.
	event Confirmation(address owner, hash operation);
	// the other is in the case of an owner changing. here we record the old and new owners.
	event OwnerChanged(address oldOwner, address newOwner);

	// constructor is given number of sigs required to do protected "onlyowners" transactions
	// as well as the selection of addresses capable of confirming them.
	function multiowned(uint _required, address[] _owners) {
		m_required = _required;
		m_owners = _owners;
	}

	// simple single-sig function modifier.
	modifier onlyowner {
		if (m_owners.find(msg.sender) != notfound)
			_
	}

	// multi-sig function modifier: the operation must have an intrinsic hash in order
	// that later attempts can be realised as the same underlying operation and
	// thus count as confirmations.
	modifier onlymanyowners(hash _operation) {
		if (confirm(_operation))
			_
	}

	function confirm(hash _operation) protected returns (bool _r) {
		// determine what index the present sender is:
		uint ownerIndex = m_owners.find(msg.sender);

		// make sure they're an owner
		if (ownerIndex != notfound) {
			// if we're not yet working on this operation, switch over and reset the confirmation status.
			if (!m_pending[_operation].yetNeeded) {
				// reset count of confirmations needed.
				m_pending[_operation].yetNeeded = _sigs.size();
				// reset which owners have confirmed (none) - set our bitmap to 0.
				m_pending[_operation].ownersDone = 0;
			}
			// determine the bit to set for this owner.
			uint ownerIndexBit = 1 << ownerIndex;

			// make sure we (the message sender) haven't confirmed this operation previously.
			assert(m_pending[_operation].yetNeeded > 0);
			if (!(m_pending[_operation].ownersDone & ownerIndexBit)) {
				Confirmation(msg.sender, _operation);
				// ok - check if count is enough to go ahead.
				if (m_pending[_operation].yetNeeded == 1) {
					// enough confirmations: reset and run interior.
					delete m_pending[_operation];
					_r = true;
				}
				else
				{
					// not enough: record that this owner in particular confirmed.
					m_pending[_operation].yetNeeded--;
					m_pending[_operation].ownersDone |= ownerIndexBit;
				}
			}
		}
	}

	// replaces an owner `_from` with another `_to`.
	function changeOwner(address _from, address _to) external multisig(sha3(msg.sig, _from, _to)) {
		uint ownerIndex = m_owners.find(_from);
		if (ownerIndex != notfound)
		{
			m_owners[ownerIndex] = _to;
			OwnerChanged(_from, _to);
		}
	}

	// the number of owners that must confirm the same operation before it is run.
	constant uint m_required;

	//stateset owners {
	set address[] m_owners;
	// set meaning you can do a fast look up into it to get the index.
	// suggested impl as combination of count-prefixed contiguous series and normal mapping for the reverse lookup:
	// sha3(BASE + 0) => N,
	// sha3(BASE + 1) => address[0],
	// ...
	// sha3(BASE + N) => address[N-1],
	// sha3(BASE ++ address[0]) => 0,
	// ...
	// sha3(BASE ++ address[N-1]) -> N-1
	//
	// provides:
	// size: m_owners.size()
	// dereference: m_owners[0], ..., m_owners[m_owners.size() - 1]
	// alteration: m_owners[2] = newValue; (original m_owners[2] is removed)
	// find: m_owners.find(m_owners[0]) == 0, ..., m_owners.find(m_owners[m_owners.size() - 1]) == m_owners.size() - 1,  m_owners.find(...) == (uint)-1 == notfound
	// append: m_owners.insert(n): m_owners[m_owners.size() - 1] == n, m_owners.lookup(n) == m_owners.size() - 1
	// delete: delete m_owners[n]
	// clear: m_owners.clear(): m_owners.size() == 0
	//}

	/*
	// for now could just be:
	uint m_ownersCount;
	mapping (uint => address) m_owners;
	mapping (address => uint) m_ownersFind;
	*/

	// the ongoing operations.
	mapping { hash => PendingState } m_pending;
}

// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable)
// on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method
// uses is specified in the modifier.
contract daylimit is multiowned {
	// constructor - just records the present day's index.
	function daylimit() {
		m_lastDay = today();
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function setDailyLimit(uint _newLimit) external onlyowners(sha3(msg.sig, _newLimit)) {
		m_dailyLimit = _newLimit;
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function resetSpentToday() external onlyowners(sha3(msg.sig)) {
		m_dailyLimit = _newLimit;
	}

	// checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
	// returns true. otherwise just returns false.
	function underLimit(uint _value) protected onlyowner {
		// reset the spend limit if we're on a different day to last time.
		if (today() > m_lastDay) {
			m_spentToday = 0;
			m_lastDay = today();
		}
		// check to see if there's enough left - if so, subtract and return true.
		if (m_spentToday + _value <= m_dailyLimit) {
			m_spendToday += _value;
			return true;
		}
		return false;
	}

	// simple modifier for daily limit.
	modifier limitedDaily(uint _value) {
		if (underLimit(_value))
			_
	}

	// determines today's index.
	function today() private constant returns (uint r) { r = block.timestamp / (60 * 60 * 24); }

	uint m_spentToday;
	uint m_dailyLimit;
	uint m_lastDay;
}

// interface contract for multisig proxy contracts.
contract multisig {
	function changeOwner(address _from, address _to);
	function transact(address _to, uint _value) returns (hash _r);
	function confirm(hash _h);
}

// usage:
// hash h = Wallet(w).from(oneOwner).transact(to, value, data);
// Wallet(w).from(anotherOwner).confirm(h);
contract Wallet is multisig multiowned daylimit {
	// Transaction structure to remember details of transaction lest it need be saved for a later call.
	structure Transaction {
		address to;
		uint value;
		byte[] data;
	}

	// logged events:
	// Funds has arrived into the wallet (record how much).
	event CashIn(uint value);
	// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
	event SingleTransact(indexed string32 = "out", address owner, uint value, address to);
	// Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
	event MultiTransact(indexed string32 = "out", address owner, hash operation, uint value, address to);

	// constructor - just pass on the owner arra to the multiowned.
	function Wallet(address[] _owners) multiowned(2, _owners) {}

	// kills the contract sending everything to `_to`.
	function kill(address _to) external onlyowners(sha3("kill", _to)) {
		this.suicide(_to);
	}

	// gets called when no other function matches
	function() {
		// just being sent some cash?
		if (msg.value) {
			CashIn(msg.value);
		}
	}

	// Outside-visible transact entry point. Executes transacion 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 transact(address _to, uint _value, bytes[] _data) external returns (hash _r) {
		// first, take the opportunity to check that we're under the daily limit.
		if (underLimit(_value)) {
			log SingleTransact(_value, _to);
			// yes - just execute the call.
			_to.call(_value, _data);
			return 0;
		}

		// determine our operation hash.
		_r = sha3("transact", _to, _value, _data);
		if (!confirm(_r) && m_txs[_r].to == 0) {
			m_txs[_r].to = _to;
			m_txs[_r].value = _value;
			m_txs[_r].data = _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(hash _h) external onlyowners(_h) {
		if (m_txs[_h].to != 0) {
			m_txs[_h].to.call(m_txs[_h].value, m_txs[_h].data);
			MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to);
			delete m_txs[_h];
		}
	}

	// internally confirm transaction with all of the info. returns true iff confirmed good and executed.
	function confirm(hash _h, address _to, uint _value, bytes[] _data) private onlyowners(_h) returns (bool _r) {
		_to.call(_value, _data);
		MultiTransact(msg.sender, _h, _value, _to);
		_r = true;
	}

	// pending transactions we have at present.
	mapping (hash => Transaction) m_txs;
}

// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a
// single, or, crucially, each of a number of, designated owners.
// usage:
// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by
// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the
// interior is executed.
contract multiowned {
	// struct for the status of a pending operation.
	struct PendingState {
		uint yetNeeded;
		uint ownersDone;
	}

	// this contract only has one type of event: it can accept a confirmation, in which case
	// we record owner and operation (hash) alongside it.
	event Confirmation(address owner, hash operation);
	event OwnerChanged(address oldOwner, address newOwner);

	// constructor is given number of sigs required to do protected "onlyowners" transactions
	// as well as the selection of addresses capable of confirming them.
	function multiowned(uint _required, address[] _owners) {
		m_required = _required;
		m_owners = _owners;
	}

	// simple single-sig function modifier.
	modifier onlyowner {
		if (m_owners.find(msg.sender) != notfound)
			_
	}

	// multi-sig function modifier: the operation must have an intrinsic hash in order
	// that later attempts can be realised as the same underlying operation and
	// thus count as confirmations.
	modifier onlymanyowners(hash _operation) {
		if (confirm(_operation))
			_
	}

	function confirm(hash _operation) protected returns (bool _r) {
		// determine what index the present sender is:
		uint ownerIndex = m_owners.find(msg.sender);

		// make sure they're an owner
		if (ownerIndex != notfound) {
			// if we're not yet working on this operation, switch over and reset the confirmation status.
			if (!m_pending[_operation].yetNeeded) {
				// reset count of confirmations needed.
				m_pending[_operation].yetNeeded = _sigs.size();
				// reset which owners have confirmed (none) - set our bitmap to 0.
				m_pending[_operation].ownersDone = 0;
			}
			// determine the bit to set for this owner.
			uint ownerIndexBit = 1 << ownerIndex;

			// make sure we (the message sender) haven't confirmed this operation previously.
			assert(m_pending[_operation].yetNeeded > 0);
			if (!(m_pending[_operation].ownersDone & ownerIndexBit)) {
				Confirmation(msg.sender, _operation);
				// ok - check if count is enough to go ahead.
				if (m_pending[_operation].yetNeeded == 1) {
					// enough confirmations: reset and run interior.
					delete m_pending[_operation];
					_r = true;
				}
				else
				{
					// not enough: record that this owner in particular confirmed.
					m_pending[_operation].yetNeeded--;
					m_pending[_operation].ownersDone |= ownerIndexBit;
				}
			}
		}
	}

	// replaces an owner `_from` with another `_to`.
	function changeOwner(address _from, address _to) external multisig(sha3(msg.sig, _from, _to)) {
		uint ownerIndex = m_owners.find(_from);
		if (ownerIndex != notfound)
		{
			m_owners[ownerIndex] = _to;
			OwnerChanged(_from, _to);
		}
	}

	// the number of owners that must confirm the same operation before it is run.
	constant uint m_required;

	//stateset owners {
	set address[] m_owners;
	// set meaning you can do a fast look up into it to get the index.
	// suggested impl as combination of count-prefixed contiguous series and normal mapping for the reverse lookup:
	// sha3(BASE + 0) => N,
	// sha3(BASE + 1) => address[0],
	// ...
	// sha3(BASE + N) => address[N-1],
	// sha3(BASE ++ address[0]) => 0,
	// ...
	// sha3(BASE ++ address[N-1]) -> N-1
	//
	// provides:
	// size: m_owners.size()
	// dereference: m_owners[0], ..., m_owners[m_owners.size() - 1]
	// alteration: m_owners[2] = newValue; (original m_owners[2] is removed)
	// find: m_owners.find(m_owners[0]) == 0, ..., m_owners.find(m_owners[m_owners.size() - 1]) == m_owners.size() - 1,  m_owners.find(...) == (uint)-1 == notfound
	// append: m_owners.insert(n): m_owners[m_owners.size() - 1] == n, m_owners.lookup(n) == m_owners.size() - 1
	// delete: delete m_owners[n]
	// clear: m_owners.clear(): m_owners.size() == 0
	//}

	/*
	// for now could just be:
	uint m_ownersCount;
	mapping (uint => address) m_owners;
	mapping (address => uint) m_ownersFind;
	*/

	// the ongoing operations.
	mapping { hash => PendingState } m_pending;
}

// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable)
// on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method
// uses is specified in the modifier.
contract daylimit is multiowned {
	// constructor - just records the present day's index.
	function daylimit() {
		m_lastDay = today();
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function setDailyLimit(uint _newLimit) external onlyowners(sha3(msg.sig, _newLimit)) {
		m_dailyLimit = _newLimit;
	}

	// (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today.
	function resetSpentToday() external onlyowners(sha3(msg.sig)) {
		m_dailyLimit = _newLimit;
	}

	// checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
	// returns true. otherwise just returns false.
	function underLimit(uint _value) protected onlyowner {
		// reset the spend limit if we're on a different day to last time.
		if (today() > m_lastDay) {
			m_spentToday = 0;
			m_lastDay = today();
		}
		// check to see if there's enough left - if so, subtract and return true.
		if (m_spentToday + _value <= m_dailyLimit) {
			m_spendToday += _value;
			return true;
		}
		return false;
	}

	// simple modifier for daily limit.
	modifier limitedDaily(uint _value) {
		if (underLimit(_value))
			_
	}

	// determines today's index.
	function today() private constant returns (uint r) { r = block.timestamp / (60 * 60 * 24); }

	uint m_spentToday;
	uint m_dailyLimit;
	uint m_lastDay;
}

// interface contract for multisig proxy contracts.
contract multisig {
	function changeOwner(address _from, address _to);
	function transact(address _to, uint _value) returns (hash _r);
	function confirm(hash _h);
}

// usage:
// hash h = Wallet(w).from(oneOwner).transact(to, value, data);
// Wallet(w).from(anotherOwner).confirm(h);
contract Wallet is multisig multiowned daylimit {
	// Transaction structure to remember details of transaction lest it need be saved for a later call.
	structure Transaction {
		address to;
		uint value;
		byte[] data;
	}

	// logged events:
	// Funds has arrived into the wallet (record how much).
	event CashIn(uint value);
	// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
	event SingleTransact(indexed string32 = "out", address owner, uint value, address to);
	// Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
	event MultiTransact(indexed string32 = "out", address owner, hash operation, uint value, address to);

	// constructor - just pass on the owner arra to the multiowned.
	function Wallet(address[] _owners) multiowned(2, _owners) {}

	// kills the contract sending everything to `_to`.
	function kill(address _to) external onlyowners(sha3("kill", _to)) {
		this.suicide(_to);
	}

	// gets called when no other function matches
	function() {
		// just being sent some cash?
		if (msg.value) {
			CashIn(msg.value);
		}
	}

	// Outside-visible transact entry point. Executes transacion 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 transact(address _to, uint _value, bytes[] _data) external returns (hash _r) {
		// first, take the opportunity to check that we're under the daily limit.
		if (underLimit(_value)) {
			log SingleTransact(_value, _to);
			// yes - just execute the call.
			_to.call(_value, _data);
			return 0;
		}

		// determine our operation hash.
		_r = sha3("transact", _to, _value, _data);
		if (!confirm(_r) && m_txs[_r].to == 0) {
			m_txs[_r].to = _to;
			m_txs[_r].value = _value;
			m_txs[_r].data = _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(hash _h) external onlyowners(_h) {
		if (m_txs[_h].to != 0) {
			m_txs[_h].to.call(m_txs[_h].value, m_txs[_h].data);
			MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to);
			delete m_txs[_h];
		}
	}

	// internally confirm transaction with all of the info. returns true iff confirmed good and executed.
	function confirm(hash _h, address _to, uint _value, bytes[] _data) private onlyowners(_h) returns (bool _r) {
		_to.call(_value, _data);
		MultiTransact(msg.sender, _h, _value, _to);
		_r = true;
	}

	// pending transactions we have at present.
	mapping (hash => Transaction) m_txs;
}


add some modifiers to poex example

add some modifiers to poex example

import "../Rejector.sol";

/*
 * Proof of Existence example contract
 * see https://medium.com/zeppelin-blog/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05
 */
contract ProofOfExistence is Rejector {

  mapping (bytes32 => bool) public proofs;

  // store a proof of existence in the contract state
  function storeProof(bytes32 proof) {
    proofs[proof] = true;
  }

  // calculate and store the proof for a document
  function notarize(string document) {
    var proof = calculateProof(document);
    storeProof(proof);
  }

  // helper function to get a document's sha256
  function calculateProof(string document) constant returns (bytes32) {
    return sha256(document);
  }

  // check if a document has been notarized
  function checkDocument(string document) constant returns (bool) {
    var proof = calculateProof(document);
    return hasProof(proof);
  }

  // returns true if proof is stored
  function hasProof(bytes32 proof) constant returns (bool) {
    return proofs[proof];
  }
}

import "../Rejector.sol";

/*
 * Proof of Existence example contract
 * see https://medium.com/zeppelin-blog/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05
 */
contract ProofOfExistence is Rejector {

  mapping (bytes32 => bool) proofs;

  // store a proof of existence in the contract state
  function storeProof(bytes32 proof) {
    proofs[proof] = true;
  }

  // calculate and store the proof for a document
  function notarize(string document) {
    var proof = calculateProof(document);
    storeProof(proof);
  }

  // helper function to get a document's sha256
  function calculateProof(string document) returns (bytes32) {
    return sha256(document);
  }

  // check if a document has been notarized
  function checkDocument(string document) returns (bool) {
    var proof = calculateProof(document);
    return hasProof(proof);
  }

  // returns true if proof is stored
  function hasProof(bytes32 proof) returns (bool) {
    return proofs[proof];
  }
}


Edit revert msg

Edit revert msg

pragma solidity >=0.8.4;

import "./ENS.sol";
import "../root/Ownable.sol";
import "../root/Controllable.sol";

abstract contract NameResolver {
    function setName(bytes32 node, string memory name) public virtual;
}

bytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000;

contract ReverseRegistrar is Ownable, Controllable {
    // namehash('addr.reverse')
    bytes32 public constant ADDR_REVERSE_NODE =
        0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;

    ENS public ens;
    NameResolver public defaultResolver;

    /**
     * @dev Constructor
     * @param ensAddr The address of the ENS registry.
     * @param resolverAddr The address of the default reverse resolver.
     */
    constructor(ENS ensAddr, NameResolver resolverAddr) {
        ens = ensAddr;
        defaultResolver = resolverAddr;

        // Assign ownership of the reverse record to our deployer
        ReverseRegistrar oldRegistrar = ReverseRegistrar(
            ens.owner(ADDR_REVERSE_NODE)
        );
        if (address(oldRegistrar) != address(0x0)) {
            oldRegistrar.claim(msg.sender);
        }
    }

    modifier authorised(address addr) {
        require(
            controllers[msg.sender] ||
                addr == msg.sender ||
                ens.isApprovedForAll(addr, msg.sender),
            "Caller is not a controller or authorised by address or the address itself"
        );
        _;
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @return The ENS node hash of the reverse record.
     */
    function claim(address owner) public returns (bytes32) {
        return _claimWithResolver(msg.sender, owner, address(0x0));
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param addr The reverse record to set
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @return The ENS node hash of the reverse record.
     */
    function claimForAddr(address addr, address owner)
        public
        authorised(addr)
        returns (bytes32)
    {
        return _claimWithResolver(addr, owner, address(0x0));
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function claimWithResolver(address owner, address resolver)
        public
        returns (bytes32)
    {
        return _claimWithResolver(msg.sender, owner, resolver);
    }

    /**
     * @dev Transfers ownership of the reverse ENS record specified with the
     *      address provided
     * @param addr The reverse record to set
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function claimWithResolverForAddr(
        address addr,
        address owner,
        address resolver
    ) public authorised(addr) returns (bytes32) {
        return _claimWithResolver(addr, owner, resolver);
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the calling account. First updates the resolver to the default reverse
     * resolver if necessary.
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setName(string memory name) public returns (bytes32) {
        bytes32 node = _claimWithResolver(
            msg.sender,
            address(this),
            address(defaultResolver)
        );
        defaultResolver.setName(node, name);
        return node;
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the account provided. First updates the resolver to the default reverse
     * resolver if necessary.
     * Only callable by controllers
     * @param addr The reverse record to set
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setNameForAddr(address addr, string memory name)
        public
        authorised(addr)
        returns (bytes32)
    {
        bytes32 node = _claimWithResolver(
            addr,
            address(this),
            address(defaultResolver)
        );
        defaultResolver.setName(node, name);
        return node;
    }

    /**
     * @dev Returns the node hash for a given account's reverse records.
     * @param addr The address to hash
     * @return The ENS node hash.
     */
    function node(address addr) public pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr))
            );
    }

    /**
     * @dev An optimised function to compute the sha3 of the lower-case
     *      hexadecimal representation of an Ethereum address.
     * @param addr The address to hash
     * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the
     *         input address.
     */
    function sha3HexAddress(address addr) private pure returns (bytes32 ret) {
        assembly {
            for {
                let i := 40
            } gt(i, 0) {

            } {
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
            }

            ret := keccak256(0, 40)
        }
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function _claimWithResolver(
        address addr,
        address owner,
        address resolver
    ) internal returns (bytes32) {
        bytes32 label = sha3HexAddress(addr);
        bytes32 node = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));
        address currentResolver = ens.resolver(node);
        bool shouldUpdateResolver = (resolver != address(0x0) &&
            resolver != currentResolver);
        address newResolver = shouldUpdateResolver ? resolver : currentResolver;

        ens.setSubnodeRecord(ADDR_REVERSE_NODE, label, owner, newResolver, 0);

        return node;
    }
}

pragma solidity >=0.8.4;

import "./ENS.sol";
import "../root/Ownable.sol";
import "../root/Controllable.sol";

abstract contract NameResolver {
    function setName(bytes32 node, string memory name) public virtual;
}

bytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000;

contract ReverseRegistrar is Ownable, Controllable {
    // namehash('addr.reverse')
    bytes32 public constant ADDR_REVERSE_NODE =
        0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;

    ENS public ens;
    NameResolver public defaultResolver;

    /**
     * @dev Constructor
     * @param ensAddr The address of the ENS registry.
     * @param resolverAddr The address of the default reverse resolver.
     */
    constructor(ENS ensAddr, NameResolver resolverAddr) {
        ens = ensAddr;
        defaultResolver = resolverAddr;

        // Assign ownership of the reverse record to our deployer
        ReverseRegistrar oldRegistrar = ReverseRegistrar(
            ens.owner(ADDR_REVERSE_NODE)
        );
        if (address(oldRegistrar) != address(0x0)) {
            oldRegistrar.claim(msg.sender);
        }
    }

    modifier authorised(address addr) {
        require(
            controllers[msg.sender] ||
                addr == msg.sender ||
                ens.isApprovedForAll(addr, msg.sender),
            "Caller is not a controller or is authori"
        );
        _;
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @return The ENS node hash of the reverse record.
     */
    function claim(address owner) public returns (bytes32) {
        return _claimWithResolver(msg.sender, owner, address(0x0));
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param addr The reverse record to set
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @return The ENS node hash of the reverse record.
     */
    function claimForAddr(address addr, address owner)
        public
        authorised(addr)
        returns (bytes32)
    {
        return _claimWithResolver(addr, owner, address(0x0));
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function claimWithResolver(address owner, address resolver)
        public
        returns (bytes32)
    {
        return _claimWithResolver(msg.sender, owner, resolver);
    }

    /**
     * @dev Transfers ownership of the reverse ENS record specified with the
     *      address provided
     * @param addr The reverse record to set
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function claimWithResolverForAddr(
        address addr,
        address owner,
        address resolver
    ) public authorised(addr) returns (bytes32) {
        return _claimWithResolver(addr, owner, resolver);
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the calling account. First updates the resolver to the default reverse
     * resolver if necessary.
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setName(string memory name) public returns (bytes32) {
        bytes32 node = _claimWithResolver(
            msg.sender,
            address(this),
            address(defaultResolver)
        );
        defaultResolver.setName(node, name);
        return node;
    }

    /**
     * @dev Sets the `name()` record for the reverse ENS record associated with
     * the account provided. First updates the resolver to the default reverse
     * resolver if necessary.
     * Only callable by controllers
     * @param addr The reverse record to set
     * @param name The name to set for this address.
     * @return The ENS node hash of the reverse record.
     */
    function setNameForAddr(address addr, string memory name)
        public
        authorised(addr)
        returns (bytes32)
    {
        bytes32 node = _claimWithResolver(
            addr,
            address(this),
            address(defaultResolver)
        );
        defaultResolver.setName(node, name);
        return node;
    }

    /**
     * @dev Returns the node hash for a given account's reverse records.
     * @param addr The address to hash
     * @return The ENS node hash.
     */
    function node(address addr) public pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr))
            );
    }

    /**
     * @dev An optimised function to compute the sha3 of the lower-case
     *      hexadecimal representation of an Ethereum address.
     * @param addr The address to hash
     * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the
     *         input address.
     */
    function sha3HexAddress(address addr) private pure returns (bytes32 ret) {
        assembly {
            for {
                let i := 40
            } gt(i, 0) {

            } {
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
            }

            ret := keccak256(0, 40)
        }
    }

    /**
     * @dev Transfers ownership of the reverse ENS record associated with the
     *      calling account.
     * @param owner The address to set as the owner of the reverse record in ENS.
     * @param resolver The address of the resolver to set; 0 to leave unchanged.
     * @return The ENS node hash of the reverse record.
     */
    function _claimWithResolver(
        address addr,
        address owner,
        address resolver
    ) internal returns (bytes32) {
        bytes32 label = sha3HexAddress(addr);
        bytes32 node = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));
        address currentResolver = ens.resolver(node);
        bool shouldUpdateResolver = (resolver != address(0x0) &&
            resolver != currentResolver);
        address newResolver = shouldUpdateResolver ? resolver : currentResolver;

        ens.setSubnodeRecord(ADDR_REVERSE_NODE, label, owner, newResolver, 0);

        return node;
    }
}


Index addreses in events and explicit uint size

pragma solidity ^0.4.11;

import "../ownership/Heritable.sol";

/**
 * @title SimpleSavingsWallet
 * @dev Simplest form of savings wallet whose ownership can be claimed by a heir
 * if owner dies.
 * In this example, we take a very simple savings wallet providing two operations
 * (to send and receive funds) and extend its capabilities by making it Heritable.
 * The account that creates the contract is set as owner, who has the authority to
 * choose an heir account. Heir account can reclaim the contract ownership in the
 * case that the owner dies.
 */
contract SimpleSavingsWallet is Heritable {

  event Sent(address indexed payee, uint256 amount, uint256 balance);
  event Received(address indexed payer, uint256 amount, uint256 balance);

  function SimpleSavingsWallet(uint256 _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}

  /**
   * @dev wallet can receive funds.
   */
  function () public payable {
    Received(msg.sender, msg.value, this.balance);
  }

  /**
   * @dev wallet can send funds
   */
  function sendTo(address payee, uint256 amount) public onlyOwner {
    require(payee != 0 && payee != address(this));
    require(amount > 0);
    payee.transfer(amount);
    Sent(payee, amount, this.balance);
  }
}

pragma solidity ^0.4.11;

import "../ownership/Heritable.sol";

/**
 * @title SimpleSavingsWallet
 * @dev Simplest form of savings wallet whose ownership can be claimed by a heir
 * if owner dies.
 * In this example, we take a very simple savings wallet providing two operations
 * (to send and receive funds) and extend its capabilities by making it Heritable.
 * The account that creates the contract is set as owner, who has the authority to
 * choose an heir account. Heir account can reclaim the contract ownership in the
 * case that the owner dies.
 */
contract SimpleSavingsWallet is Heritable {

  event Sent(address payee, uint amount, uint balance);
  event Received(address payer, uint amount, uint balance);

  function SimpleSavingsWallet(uint _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}

  /**
   * @dev wallet can receive funds.
   */
  function () public payable {
    Received(msg.sender, msg.value, this.balance);
  }

  /**
   * @dev wallet can send funds
   */
  function sendTo(address payee, uint amount) public onlyOwner {
    require(payee != 0 && payee != address(this));
    require(amount > 0);
    payee.transfer(amount);
    Sent(payee, amount, this.balance);
  }
}


Fix issue with insertNodesBatch (update last node with new node info)

pragma solidity^0.4.11;

import "../libraries/TreeLib.sol";

contract Tree{

    mapping(bytes32=>TreeLib.Index) indexes;//Or a single index, based on how you want to arange your indexes
    mapping(bytes32=>bytes32) parent_child_lookup;

    uint max_depth=2; // Maxdepth of the tree; advised 5
    uint mtypes_count=3;//Count of mtypes,available structure types from the lib
    bytes8[3] mtypes = [ bytes8("Node"), bytes8("Section"), bytes8("Index")]; //Increase type to match structure types
    enum ltypes {Node,Section,Index} //Increase type to match structure types

    uint parent_max_size = 10; //Max size for all parents equaling Max nodes = parent_max_size^(max_depth-1)

    function TreeContract(){
    }

    function indexExists(bytes32 index_id) constant returns (bool){
        return (indexes[index_id].id == index_id);
    }

    function childExists(bytes32 child_id) constant returns(bool){
        return (getParent(child_id) != 0x0);
    }

    function nodeExists(bytes32 index_id,bytes32 node_id) constant returns(bool){
        if(childExists(node_id) ){
          return getHeirachy(node_id)[1] == index_id;
        }
        return false;
    }

    function getParent(bytes32 child_id) constant returns(bytes32){
        return parent_child_lookup[child_id];
    }

    function getHeirachy(bytes32 child_id) constant returns (bytes32[2] memory search_up /*should match (max_depth)*/){
        bytes32 main_index_id;

        //Fetch the node's parent
        main_index_id = getParent(child_id);
        search_up[0] = main_index_id;

        uint i = 1;
        while((main_index_id = getParent(main_index_id)) != 0x0){
        search_up[i] = main_index_id;
        i++;
        }
    }

    function nextSection(bytes32 index_id) internal constant returns (bytes32 id){
      //get the next available section in the index
      TreeLib.Index storage index = indexes[index_id];
      id = indexes[index_id].root;
      while(true){
        if(index.children[id].size+1 > index.maxsize && index.children[id].id != 0x0){
          id = index.children[id].right;
          continue;
        }
        else break;
      }
      return id;
    }

    function getSection(bytes32 section_id) internal constant returns(TreeLib.Section storage sector){
        bytes32[2] memory search_up; //size should match (max_depth)
        search_up = getHeirachy(section_id);

        //GenecricTree.SubSection storage subsector; //Only enabled if max_dept >2
        //Structure based on sector parent being index
        if(search_up.length>0){
          sector = indexes[search_up[0]].children[section_id];
        }
    }

    function getIndex(bytes32 index_id)constant returns(uint mtype,uint size, uint maxsize, bytes32 id, bytes32 root, bytes32 last){

        TreeLib.Index memory index = indexes[index_id];
        return (index.mtype,index.size,index.maxsize,index.id,index.root,index.last);
    }

    function getNode(bytes32 node_id) constant returns (bytes32 id,bytes32 left,bytes32 right,bytes32 parent,bytes32 data){
        //set returns based on nature of base node
        //require(child_type_lookup[node_id] == ltypes.Node);
        return TreeLib.getNode(getSection(getParent(node_id)),node_id);
    }

    function getNodesBatch(bytes32 index_id,bytes32 last_node_id) constant returns (bytes32[5][5] results) {
          TreeLib.Index storage index = indexes[index_id];

          //throw if empty
          require(index.size>0);

          if(last_node_id == 0x0)last_node_id = index.children[index.root].root;
          else last_node_id = index.children[getParent(last_node_id)].children[last_node_id].right;

          bytes32 section_id = getParent(last_node_id);
          TreeLib.Section storage sector = index.children[section_id];

          uint r = 0;

          while(r<5 && last_node_id!=0x0){
           results[0][r]= sector.children[last_node_id].id;
           results[1][r]= sector.children[last_node_id].left;
           results[2][r]= sector.children[last_node_id].right;
           results[3][r]= sector.children[last_node_id].parent;
           results[4][r]= sector.children[last_node_id].data;
           r++;

           if(sector.children[last_node_id].right == 0x0){
             if(sector.right != 0x0){
               sector = index.children[sector.right];
               last_node_id = sector.root;
               continue;
             }
           break;
           }
           else {
             last_node_id = sector.children[last_node_id].right;}
          }

          return results;
    }

    function generateSection() returns (bytes32 section_id){
      uint i = 0;
      while(childExists(sha3(block.difficulty+i,block.number+i,block.timestamp+1))){
        i++;
      }
      return sha3(block.difficulty+i,block.number+i,block.timestamp+1);
    }

    function newIndex(bytes32 index_id)idNotEmpty(index_id){
        indexes[index_id] = TreeLib.newIndex(index_id,parent_max_size);
    }

    function insertSection(bytes32 parent_id) returns(bytes32){
        //Create new index, if it does not exist
        if(!indexExists(parent_id))
          newIndex(parent_id);

        bytes32 section_id = generateSection();

        //Parent is an Index, store as child of index
        TreeLib.Index storage index = indexes[parent_id];
        parent_child_lookup[section_id] =  parent_id;
        TreeLib.insertSection(index,section_id);
        return section_id;
    }

    function insertNode(bytes32 index_id, bytes32 node_id, bytes32 data){
        //Ensure index and node are not empty
        require(index_id!= 0x0 && node_id != 0x0);

        //Create new index, if it does not exist
        if(!indexExists(index_id))
          newIndex(index_id);

        //check to see the next available sector
        bytes32 section_id = nextSection(index_id);
        if(section_id == 0x0)
          section_id = insertSection(index_id);

        parent_child_lookup[node_id] =  section_id;
        TreeLib.insertNode(getSection(section_id),node_id,data);
    }

    function insertNodeBatch(bytes32 index_id, bytes32[2][5] data){
      require(index_id!= 0x0);

      //Create new index, if it does not exist
      if(!indexExists(index_id))
        newIndex(index_id);

      //check to see the next available sector
      bytes32 section_id = nextSection(index_id);
      if(section_id == 0x0)
        section_id = insertSection(index_id);
      uint to_fill = indexes[index_id].children[section_id].maxsize - indexes[index_id].children[section_id].size;

      for(uint d=0;d<data.length;d++){
        bytes32 node_id = data[d][0];
        bytes32 node_data = data[d][1];
        //Ensure index and node are not empty
        if(node_id == 0x0)
        continue;

        //Generate new sector if exceeded
        if(to_fill < d){
          section_id = nextSection(index_id);
          if(section_id == 0x0)
            section_id = insertSection(index_id);
          to_fill += indexes[index_id].children[section_id].maxsize - indexes[index_id].children[section_id].size;
        }

        bytes32 right = 0x0;
        bytes32 left = 0x0;
        if(d==0){
          TreeLib.Section storage sector = getSection(section_id);
          left = sector.last;
          sector.children[left].right = node_id;
        }
        else{
          left = data[d-1][0];
        }
        if(data.length>d+1)
          right = data[d+1][0];

        parent_child_lookup[node_id] =  section_id;
        TreeLib.insertNodeBatch(getSection(section_id),left,right,node_id,node_data);
      }
    }

    modifier idNotEmpty(bytes32 id){
        require(id != 0x0);
        _;
    }

}

pragma solidity^0.4.11;

import "../libraries/TreeLib.sol";

contract Tree{

    mapping(bytes32=>TreeLib.Index) indexes;//Or a single index, based on how you want to arange your indexes
    mapping(bytes32=>bytes32) parent_child_lookup;

    uint max_depth=2; // Maxdepth of the tree; advised 5
    uint mtypes_count=3;//Count of mtypes,available structure types from the lib
    bytes8[3] mtypes = [ bytes8("Node"), bytes8("Section"), bytes8("Index")]; //Increase type to match structure types
    enum ltypes {Node,Section,Index} //Increase type to match structure types

    uint parent_max_size = 10; //Max size for all parents equaling Max nodes = parent_max_size^(max_depth-1)

    function TreeContract(){
    }

    function indexExists(bytes32 index_id) constant returns (bool){
        return (indexes[index_id].id == index_id);
    }

    function childExists(bytes32 child_id) constant returns(bool){
        return (getParent(child_id) != 0x0);
    }

    function nodeExists(bytes32 index_id,bytes32 node_id) constant returns(bool){
        if(childExists(node_id) ){
          return getHeirachy(node_id)[1] == index_id;
        }
        return false;
    }

    function getParent(bytes32 child_id) constant returns(bytes32){
        return parent_child_lookup[child_id];
    }

    function getHeirachy(bytes32 child_id) constant returns (bytes32[2] memory search_up /*should match (max_depth)*/){
        bytes32 main_index_id;

        //Fetch the node's parent
        main_index_id = getParent(child_id);
        search_up[0] = main_index_id;

        uint i = 1;
        while((main_index_id = getParent(main_index_id)) != 0x0){
        search_up[i] = main_index_id;
        i++;
        }
    }

    function nextSection(bytes32 index_id) internal constant returns (bytes32 id){
      //get the next available section in the index
      TreeLib.Index storage index = indexes[index_id];
      id = indexes[index_id].root;
      while(true){
        if(index.children[id].size+1 > index.maxsize && index.children[id].id != 0x0){
          id = index.children[id].right;
          continue;
        }
        else break;
      }
      return id;
    }

    function getSection(bytes32 section_id) internal constant returns(TreeLib.Section storage sector){
        bytes32[2] memory search_up; //size should match (max_depth)
        search_up = getHeirachy(section_id);

        //GenecricTree.SubSection storage subsector; //Only enabled if max_dept >2
        //Structure based on sector parent being index
        if(search_up.length>0){
          sector = indexes[search_up[0]].children[section_id];
        }
    }

    function getIndex(bytes32 index_id)constant returns(uint mtype,uint size, uint maxsize, bytes32 id, bytes32 root, bytes32 last){

        TreeLib.Index memory index = indexes[index_id];
        return (index.mtype,index.size,index.maxsize,index.id,index.root,index.last);
    }

    function getNode(bytes32 node_id) constant returns (bytes32 id,bytes32 left,bytes32 right,bytes32 parent,bytes32 data){
        //set returns based on nature of base node
        //require(child_type_lookup[node_id] == ltypes.Node);
        return TreeLib.getNode(getSection(getParent(node_id)),node_id);
    }

    function getNodesBatch(bytes32 index_id,bytes32 last_node_id) constant returns (bytes32[5][5] results) {
          TreeLib.Index storage index = indexes[index_id];

          //throw if empty
          require(index.size>0);

          if(last_node_id == 0x0)last_node_id = index.children[index.root].root;
          else last_node_id = index.children[getParent(last_node_id)].children[last_node_id].right;

          bytes32 section_id = getParent(last_node_id);
          TreeLib.Section storage sector = index.children[section_id];

          uint r = 0;

          while(r<5 && last_node_id!=0x0){
           results[0][r]= sector.children[last_node_id].id;
           results[1][r]= sector.children[last_node_id].left;
           results[2][r]= sector.children[last_node_id].right;
           results[3][r]= sector.children[last_node_id].parent;
           results[4][r]= sector.children[last_node_id].data;
           r++;

           if(sector.children[last_node_id].right == 0x0){
             if(sector.right != 0x0){
               sector = index.children[sector.right];
               last_node_id = sector.root;
               continue;
             }
           break;
           }
           else {
             last_node_id = sector.children[last_node_id].right;}
          }

          return results;
    }

    function generateSection() returns (bytes32 section_id){
      uint i = 0;
      while(childExists(sha3(block.difficulty+i,block.number+i,block.timestamp+1))){
        i++;
      }
      return sha3(block.difficulty+i,block.number+i,block.timestamp+1);
    }

    function newIndex(bytes32 index_id)idNotEmpty(index_id){
        indexes[index_id] = TreeLib.newIndex(index_id,parent_max_size);
    }

    function insertSection(bytes32 parent_id) returns(bytes32){
        //Create new index, if it does not exist
        if(!indexExists(parent_id))
          newIndex(parent_id);

        bytes32 section_id = generateSection();

        //Parent is an Index, store as child of index
        TreeLib.Index storage index = indexes[parent_id];
        parent_child_lookup[section_id] =  parent_id;
        TreeLib.insertSection(index,section_id);
        return section_id;
    }

    function insertNode(bytes32 index_id, bytes32 node_id, bytes32 data){
        //Ensure index and node are not empty
        require(index_id!= 0x0 && node_id != 0x0);

        //Create new index, if it does not exist
        if(!indexExists(index_id))
          newIndex(index_id);

        //check to see the next available sector
        bytes32 section_id = nextSection(index_id);
        if(section_id == 0x0)
          section_id = insertSection(index_id);

        parent_child_lookup[node_id] =  section_id;
        TreeLib.insertNode(getSection(section_id),node_id,data);
    }

    function insertNodeBatch(bytes32 index_id, bytes32[2][5] data){
      require(index_id!= 0x0);

      //Create new index, if it does not exist
      if(!indexExists(index_id))
        newIndex(index_id);

      //check to see the next available sector
      bytes32 section_id = nextSection(index_id);
      if(section_id == 0x0)
        section_id = insertSection(index_id);
      uint to_fill = indexes[index_id].children[section_id].maxsize - indexes[index_id].children[section_id].size;

      for(uint d=0;d<data.length;d++){
        bytes32 node_id = data[d][0];
        bytes32 node_data = data[d][1];
        //Ensure index and node are not empty
        if(node_id == 0x0)
        continue;

        //Generate new sector if exceeded
        if(to_fill < d){
          section_id = nextSection(index_id);
          if(section_id == 0x0)
            section_id = insertSection(index_id);
          to_fill += indexes[index_id].children[section_id].maxsize - indexes[index_id].children[section_id].size;
        }

        bytes32 right = 0x0;
        bytes32 left = 0x0;
        if(d==0){
          left = getSection(section_id).last;
        }
        else{
          left = data[d-1][0];
        }
        if(data.length>d+1)
          right = data[d+1][0];

        parent_child_lookup[node_id] =  section_id;
        TreeLib.insertNodeBatch(getSection(section_id),left,right,node_id,node_data);
      }
    }

    modifier idNotEmpty(bytes32 id){
        require(id != 0x0);
        _;
    }

}


fixed issues with first query being free and allowed to contracts to be micro settled intraday.

/*
    Copyright 2017 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.0;

import "./Creatable.sol";
import "./Oraclize/oraclizeAPI.sol";

//TODO: fix style issues
//      add accounting for users and positions
//      how to hold ether for needed gas
//      how to hold collateral pool
//      add failsafe for pool distribution.
contract MarketContract is Creatable, usingOraclize  {

    // constants
    string public CONTRACT_NAME;
    address public BASE_TOKEN;
    uint public PRICE_CAP;
    uint public PRICE_FLOOR;
    uint public PRICE_DECIMAL_PLACES;   // how to convert the pricing from decimal format (if valid) to integer
    uint public EXPIRATION;
    string public ORACLE_DATA_SOURCE;
    string public ORACLE_QUERY;
    uint public ORACLE_QUERY_REPEAT;
    uint8 public BUY_SIDE = 0;
    uint8 public SELL_SIDE = 1;
    uint public COST_PER_QUERY = 2 finney;    // leave static for now, price of first query from oraclize is 0

    // state variables
    string public lastPriceQueryResult;
    uint public lastPrice;
    bool public isExpired;
    mapping(bytes32 => bool) validQueryIDs;

    // how to map user to position?
    event NewOracleQuery(string description);
    event UpdatedLastPrice(string price);
    event ContractSettled();

    struct Order {
        address maker;
        address taker;
        uint qty;
        uint price;
        uint8 makerSide;
        uint expirationTimeStamp;
        bytes32 orderHash;
    }

    function MarketContract(
        string contractName,
        address baseToken,
        string oracleDataSource,
        string oracleQuery,
        uint oracleQueryRepeatSeconds,
        uint floorPrice,
        uint capPrice,
        uint priceDecimalPlaces,
        uint secondsToExpiration) payable {

        require(capPrice > floorPrice);
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
        CONTRACT_NAME = contractName;
        BASE_TOKEN = baseToken;
        PRICE_CAP = capPrice;
        PRICE_FLOOR = floorPrice;
        EXPIRATION = now + secondsToExpiration;
        ORACLE_DATA_SOURCE = oracleDataSource;
        ORACLE_QUERY = oracleQuery;
        ORACLE_QUERY_REPEAT = oracleQueryRepeatSeconds;
        PRICE_DECIMAL_PLACES = priceDecimalPlaces;
        require(checkSufficientStartingBalance(secondsToExpiration));
        queryOracle();  // schedules recursive calls to oracle
    }

    function __callback(bytes32 queryID, string result, bytes proof) {
        require(validQueryIDs[queryID]);
        require(msg.sender == oraclize_cbAddress());
        lastPriceQueryResult = result;
        lastPrice = parseInt(result, PRICE_DECIMAL_PLACES);
        UpdatedLastPrice(result);
        delete validQueryIDs[queryID];
        checkSettlement();
        if (!isExpired) {
            queryOracle();  // set up our next query
        }
    }

    function queryOracle() internal
    {
        if (oraclize_getPrice(ORACLE_DATA_SOURCE) > this.balance) {
            NewOracleQuery("Oraclize query was NOT sent, please add some ETH to cover for the query fee");
            lastPriceQueryResult = "FAILED"; //TODO: failsafe
        } else {
            NewOracleQuery("Oraclize query was sent, standing by for the answer..");
            bytes32 queryId = oraclize_query(ORACLE_QUERY_REPEAT, ORACLE_DATA_SOURCE, ORACLE_QUERY);
            validQueryIDs[queryId] = true;
        }
    }

    function checkSettlement() internal
    {
        if(isExpired)   // already expired.
            return;

        if(now > EXPIRATION) {
            isExpired = true;   // time based expiration has occurred.
        } else if(lastPrice >= PRICE_CAP || lastPrice <= PRICE_FLOOR) {
            isExpired = true;   // we have breached/touched our pricing bands
        }

        if(isExpired) {
            settleContract();
        }
    }

    function settleContract() internal
    {
        // TODO: build mechanism for distribution of collateral
        ContractSettled();
    }

    // for now lets require alot of padding for the settlement,
    function checkSufficientStartingBalance(uint secondsToExpiration) private returns (bool isSufficient) {
        //uint costPerQuery = oraclize_getPrice(ORACLE_DATA_SOURCE); this doesn't work prior to first query(its free)
        uint expectedNoOfQueries = secondsToExpiration / ORACLE_QUERY_REPEAT;
        uint approxGasRequired = COST_PER_QUERY * expectedNoOfQueries;
        return this.balance > (approxGasRequired * 2);
    }
}

/*
    Copyright 2017 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.0;

import "./Creatable.sol";
import "./Oraclize/oraclizeAPI.sol";

//TODO: fix style issues
//      add accounting for users and positions
//      how to hold ether for needed gas
//      how to hold collateral pool
//      add failsafe for pool distribution.
contract MarketContract is Creatable, usingOraclize  {

    // constants
    string public CONTRACT_NAME;
    address public BASE_TOKEN;
    uint public PRICE_CAP;
    uint public PRICE_FLOOR;
    uint public PRICE_DECIMAL_PLACES;   // how to convert the pricing from decimal format (if valid) to integer
    uint public EXPIRATION;
    string public ORACLE_DATA_SOURCE;
    string public ORACLE_QUERY;
    uint public ORACLE_QUERY_REPEAT;
    uint8 public BUY_SIDE = 0;
    uint8 public SELL_SIDE = 1;

    // state variables
    string public lastPriceQueryResult;
    uint public lastPrice;
    bool public isExpired;
    mapping(bytes32 => bool) validQueryIDs;

    // how to map user to position?
    event NewOracleQuery(string description);
    event UpdatedLastPrice(string price);
    event ContractSettled();

    struct Order {
        address maker;
        address taker;
        uint qty;
        uint price;
        uint8 makerSide;
        uint expirationTimeStamp;
        bytes32 orderHash;
    }

    function MarketContract(
        string contractName,
        address baseToken,
        string oracleDataSource,
        string oracleQuery,
        uint oracleQueryRepeatSeconds,
        uint floorPrice,
        uint capPrice,
        uint priceDecimalPlaces,
        uint daysToExpiration) payable {

        require(capPrice > floorPrice);
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
        CONTRACT_NAME = contractName;
        BASE_TOKEN = baseToken;
        PRICE_CAP = capPrice;
        PRICE_FLOOR = floorPrice;
        uint secondsToExpiration = daysToExpiration * 1 days;
        EXPIRATION = now + secondsToExpiration;
        ORACLE_DATA_SOURCE = oracleDataSource;
        ORACLE_QUERY = oracleQuery;
        ORACLE_QUERY_REPEAT = oracleQueryRepeatSeconds;
        PRICE_DECIMAL_PLACES = priceDecimalPlaces;
        require(checkSufficientStartingBalance(secondsToExpiration));
        queryOracle();  // schedules recursive calls to oracle
    }

    function __callback(bytes32 queryID, string result, bytes proof) {
        require(validQueryIDs[queryID]);
        require(msg.sender == oraclize_cbAddress());
        lastPriceQueryResult = result;
        lastPrice = parseInt(result, PRICE_DECIMAL_PLACES);
        UpdatedLastPrice(result);
        delete validQueryIDs[queryID];
        checkSettlement();
        if (!isExpired) {
            queryOracle();  // set up our next query
        }
    }

    function queryOracle() internal
    {
        if (oraclize_getPrice(ORACLE_DATA_SOURCE) > this.balance) {
            NewOracleQuery("Oraclize query was NOT sent, please add some ETH to cover for the query fee");
            lastPriceQueryResult = "FAILED"; //TODO: failsafe
        } else {
            NewOracleQuery("Oraclize query was sent, standing by for the answer..");
            bytes32 queryId = oraclize_query(ORACLE_QUERY_REPEAT, ORACLE_DATA_SOURCE, ORACLE_QUERY);
            validQueryIDs[queryId] = true;
        }
    }

    function checkSettlement() internal
    {
        if(isExpired)   // already expired.
            return;

        if(now > EXPIRATION) {
            isExpired = true;   // time based expiration has occurred.
        } else if(lastPrice >= PRICE_CAP || lastPrice <= PRICE_FLOOR) {
            isExpired = true;   // we have breached/touched our pricing bands
        }

        if(isExpired) {
            settleContract();
        }
    }

    function settleContract() internal
    {
        // TODO: build mechanism for distribution of collateral
        ContractSettled();
    }

    // for now lets require alot of padding for the settlement,
    function checkSufficientStartingBalance(uint secondsToExpiration) private returns (bool isSufficient) {
        uint approxQueriesRequired = secondsToExpiration / ORACLE_QUERY_REPEAT;
        uint approxGasRequired = oraclize_getPrice(ORACLE_DATA_SOURCE) * approxQueriesRequired;
        return this.balance > (approxGasRequired * 2);
    }
}


TokenWithEStop: space for consistent style.

contract TokenWithEStop {
  mapping(address => uint) public balanceOf;
  address public curator;
  bool public stopped;
  uint public totalSupply;

  modifier stopInEmergency { if (!stopped) _ }
  modifier onlyInEmergency { if (stopped) _ }

  function TokenWithEStop(address _curator) {
    curator = _curator;
  }

  function deposit(uint amount) stopInEmergency {
    // intentionally vulnerable
    balanceOf[msg.sender] += amount;
    totalSupply += amount;
  }

  function transfer(address to, uint value) stopInEmergency {
    if (balanceOf[msg.sender] >= value) {
      balanceOf[to] += value;
      balanceOf[msg.sender] -= value;
    }
  }

  function emergencyStop() {
    if (msg.sender == curator) {
      stopped = true;
    }
  }

  function withdraw() onlyInEmergency {
    uint balance = balanceOf[msg.sender];
    balanceOf[msg.sender] = 0;
    totalSupply -= balance;

    if(!msg.sender.send(balance)) throw;
  }
}

contract TokenWithEStop {
  mapping(address => uint) public balanceOf;
  address public curator;
  bool public stopped;
  uint public totalSupply;

  modifier stopInEmergency { if (!stopped) _ }
  modifier onlyInEmergency { if (stopped) _ }

  function TokenWithEStop(address _curator) {
    curator = _curator;
  }

  function deposit(uint amount) stopInEmergency {
    // intentionally vulnerable
    balanceOf[msg.sender] += amount;
    totalSupply += amount;
  }

  function transfer(address to, uint value) stopInEmergency {
    if (balanceOf[msg.sender] >= value) {
      balanceOf[to] += value;
      balanceOf[msg.sender] -= value;
    }
  }

  function emergencyStop() {
    if (msg.sender == curator) {
      stopped = true;
    }
  }

  function withdraw() onlyInEmergency{
    uint balance = balanceOf[msg.sender];
    balanceOf[msg.sender] = 0;
    totalSupply -= balance;

    if(!msg.sender.send(balance)) throw;
  }
}


update Math.sol path (#1319)

update Math.sol path (#1319)

pragma solidity ^0.4.24;

import "../math/Math.sol";

contract MathMock {
  function max(uint256 a, uint256 b) public pure returns (uint256) {
    return Math.max(a, b);
  }

  function min(uint256 a, uint256 b) public pure returns (uint256) {
    return Math.min(a, b);
  }

  function average(uint256 a, uint256 b) public pure returns (uint256) {
    return Math.average(a, b);
  }
}

pragma solidity ^0.4.24;

import "../../contracts/math/Math.sol";

contract MathMock {
  function max(uint256 a, uint256 b) public pure returns (uint256) {
    return Math.max(a, b);
  }

  function min(uint256 a, uint256 b) public pure returns (uint256) {
    return Math.min(a, b);
  }

  function average(uint256 a, uint256 b) public pure returns (uint256) {
    return Math.average(a, b);
  }
}


solidity: add T01_Storage.sol

solidity: add T01_Storage.sol

pragma solidity ^0.4.11;
//
// https://ethereum.github.io/browser-solidity/
// import "github.com/dltdojo/courses/solidity/T01_Storage.sol"
//
// http://solidity.readthedocs.io/en/develop/introduction-to-smart-contracts.html
//
contract Foo {
  uint storedData;
  function set(uint x) {
    storedData = x;
  }
}

contract FooGet is Foo {
  function get() constant returns (uint) {
    return storedData;
  }
}

/*
The keyword public automatically generates a function that allows you to access the current value of the state variable.
*/
contract FooPublic is Foo {
  uint public storedData;
}

contract FooPublicPow2 is FooPublic {
  function pow2() returns (uint res){
    res = storedData **2 ;
  }
}

contract FooPublicPow2Save is FooPublic {
  function pow2() returns (uint res){
    res = storedData **2 ;
    storedData = res;
  }
}

error: pathspec 'solidity/T01_Storage.sol' did not match any file(s) known to git


Move core into separate repo

Move core into separate repo

contract token {
    address public daoAddr;
    address public owner;
    mapping (address => uint) public tokenBalanceOf;
    DAO daoToken;

    /*Initial */
    function token() {
        owner = msg.sender;
    }

    /* DAO functions */
    function emission(address _agentContrAddr, uint _amount) returns(bool result) {
        if(msg.sender==daoAddr)
        {
            tokenBalanceOf[_agentContrAddr] += _amount;
            return true;
        }
        return false;
    }

    function burn(address _agentContrAddr, uint _amount) returns(bool result) {
        if(msg.sender==daoAddr && tokenBalanceOf[_agentContrAddr]>=_amount)
        {
            tokenBalanceOf[_agentContrAddr] -= _amount;
            return true;
        }
        return false;
    }

    function setDaoAddr(address _daoAddr) {
        daoToken = DAO(_daoAddr);
        if(daoToken.daoFounder() == msg.sender && owner == msg.sender) {
            daoAddr = _daoAddr;
        }
    }

    /* Agent function */

    function getBalance() returns(uint _balance) {
        return tokenBalanceOf[msg.sender];
    }

    function sendToken(address receiver, uint amount) returns(bool result) {
        if (tokenBalanceOf[msg.sender] < amount) {return false;}
        tokenBalanceOf[msg.sender] -= amount;
        tokenBalanceOf[receiver] += amount;
        return true;
    }
}

contract DAO {

    address public daoFounder;
    address public daoFounderContr;
    address public daoMarketContr;
    address public daoGovermentContr;
    bool public initialization;
    uint public creditAmount;
    uint public sharesAmount;
    uint public creditTurn;
    uint public numAgents;

    token public daoShares;
    token public daoCredits;

    /* Assets data */
    Asset[] public assetsList;
    mapping (address => uint) public assetDataOf;
    mapping (address => bool) public assetExistOf;
    struct Asset {
        address assetAddr;
    }

    /* Agents data */
    Agent[] public agentsList;
    mapping (address => uint) public agentDataOf;
    mapping (address => bool) public agentActiveOf;
    struct Agent {
        address agentContrAddr;
        uint joinData;
    }

    function DAO(token _shares, token _credits, market _daoMarketContr, goverment _daoGovermentContr) {
        daoFounder = msg.sender;
        daoShares = token(_shares);
        daoCredits = token(_credits);
        daoMarketContr = _daoMarketContr;
        daoGovermentContr = _daoGovermentContr;
    }

    function initializationDaoBalances(uint _founderSharesAmount, uint _founderCreditsAmount) returns (bool result) {
        if(!initialization) {
        daoShares.emission(msg.sender, _founderSharesAmount);
        sharesAmount = _founderSharesAmount;
        daoCredits.emission(msg.sender, _founderCreditsAmount);
        creditAmount = _founderCreditsAmount;
        return true;
        }
    }

    function daoEfficiency() returns (uint daoEfficiency) {
        daoEfficiency = creditTurn*100/creditAmount;
    }

    function daoShareCost() returns (uint shareCost) {
        shareCost = creditTurn/sharesAmount;
    }

    function daoCreditPower() returns (uint creditPower) {
        creditPower = sharesAmount*100/creditTurn;
    }

    function daoShareSale(uint _shareAmount) returns (uint creditReward) {
        if(daoShares.tokenBalanceOf(msg.sender)>=_shareAmount) {
            creditReward = daoShareCost()*_shareAmount;
            daoCredits.emission(msg.sender, creditReward);
            daoShares.burn(msg.sender, _shareAmount);
        }
    }

    function daoShareBuy(uint _creditAmount) returns (uint shares) {
        if(daoCredits.tokenBalanceOf(msg.sender)>=_creditAmount) {
            shares = daoCreditPower()*_creditAmount;
            daoShares.emission(msg.sender, shares);
            daoCredits.burn(msg.sender, _creditAmount);
        }
    }

    function daoSharesEmission(address _agentContrAddr, uint _sharesAmount) {
        daoShares.emission(_agentContrAddr, _sharesAmount);
    }

    function daoCreditEmission(uint _creditsAMount) {
        daoCredits.emission(msg.sender, _creditsAMount);
    }

    function setAgent(address _agentContAddr) returns(uint agentID) {
        if(daoShares.tokenBalanceOf(msg.sender)>0) {
            agentID = agentsList.length++;
            Agent a = agentsList[agentID];
            a.agentContrAddr = _agentContAddr;
            a.joinData = now;
            uint newAgentSharesAmount;
            newAgentSharesAmount = sharesAmount/numAgents;
            daoShares.emission(_agentContAddr, newAgentSharesAmount);
            numAgents = agentID;
            agentDataOf[_agentContAddr] = agentID;
            agentActiveOf[_agentContAddr] = true;
            return agentID;
        }
    }

    function setAssets(address _assetAddr) returns(uint assetID) {
        if (msg.sender == daoMarketContr) {
            assetID = assetsList.length++;
            Asset a = assetsList[assetID];
            a.assetAddr = _assetAddr;
            assetDataOf[_assetAddr] = assetID;
            assetExistOf[_assetAddr] = true;
            return assetID;
        }
    }
}

contract agent {
    address agentAddr;
    address controlAddr;
    address daoAddr;
    DAO public dao;

    modifier controlCheck { if (msg.sender == controlAddr) _ }

    function agent(address _daoAddr) {
        agentAddr = msg.sender;
        controlAddr = msg.sender;
        daoAddr = _daoAddr;
    }

    function setControlAddr(address _controlAddr) returns(bool result) {
        if(msg.sender == agentAddr) {
            controlAddr = _controlAddr;
        }
    }

    function setAgent(address _agentAddr) controlCheck returns(bool result) {
        dao.setAgent(_agentAddr);
        return true;
    }
}

contract market {
    address daoAddr;
    DAO public dao;

    struct Order {
        address owner;
        uint amount;
    }

    struct OrderList {
        address assetAddr;
        Order[] orders;
    }

    OrderList[] public sellList;
    mapping (address => bool) sellExistOf;
    mapping (address => uint) sellDataOf;

    OrderList[] public buyList;
    mapping (address => bool) buyExistOf;
    mapping (address => uint) buyDataOf;

    function getSellList(address _assetAddr) returns(uint assetID) {
        return 0;
    }

    function getBuyList(address _assetAddr) returns(uint assetID) {
        return 0;
    }

    function addSell(address _assetAddr, uint amount) returns(uint assetID) {
        return 0;
    }

    function addBuy(address _assetAddr, uint _amount) returns(uint buyID) {
        if (dao.agentActiveOf(msg.sender) && dao.assetExistOf(_assetAddr)) {
            if(buyExistOf[_assetAddr]) {
                uint assetID;
                assetID = buyDataOf[_assetAddr];
                OrderList[] buyOrders = buyList[assetID];
                buyID = buyOrders.orders.length++;
                buyOrders.orders[buyID] = Order({owner: msg.sender, amount: _amount});
                return assetID;
            }

        }
    }
}

contract goverment {

}


Update ERC777 event documentation (#3594)

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/IERC777.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC777Token standard as defined in the EIP.
 *
 * This contract uses the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
 * token holders and recipients react to token movements by using setting implementers
 * for the associated interfaces in said registry. See {IERC1820Registry} and
 * {ERC1820Implementer}.
 */
interface IERC777 {
    /**
     * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.
     *
     * Note that some additional user `data` and `operatorData` can be logged in the event.
     */
    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);

    /**
     * @dev Emitted when `operator` destroys `amount` tokens from `account`.
     *
     * Note that some additional user `data` and `operatorData` can be logged in the event.
     */
    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);

    /**
     * @dev Emitted when `operator` is made operator for `tokenHolder`.
     */
    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    /**
     * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`.
     */
    event RevokedOperator(address indexed operator, address indexed tokenHolder);

    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For most token contracts, this value will equal 1.
     */
    function granularity() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by an account (`owner`).
     */
    function balanceOf(address owner) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(
        address recipient,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external;

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external;

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external;

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/IERC777.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC777Token standard as defined in the EIP.
 *
 * This contract uses the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
 * token holders and recipients react to token movements by using setting implementers
 * for the associated interfaces in said registry. See {IERC1820Registry} and
 * {ERC1820Implementer}.
 */
interface IERC777 {
    /**
     * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.
     *
     * Note that some additional user `data` and `operatorData` can be logged in the event.
     */
    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);

    /**
     * @dev Emitted when `operator` destroys `amount` tokens from `account`.
     *
     * Note that some additional user `data` and `operatorData` can be logged in the event.
     */
    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);

    /**
     * @dev Emitted when `operator` is made operator for `tokenHolder`
     */
    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    /**
     * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`
     */
    event RevokedOperator(address indexed operator, address indexed tokenHolder);

    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For most token contracts, this value will equal 1.
     */
    function granularity() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by an account (`owner`).
     */
    function balanceOf(address owner) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(
        address recipient,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external;

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external;

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external;

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );
}