Nicer side-docs.

Nicer side-docs.

// NameReg
// Simple global name registrar.
// @authors:
//   kobigurk (from #ethereum-dev)
//   Gav Wood <g@ethdev.com>

contract Config{function register(uint _,address __){}function unregister(uint _){}function lookup(uint _)constant returns(address __){}function kill(){}}

contract NameReg {
	function NameReg() {
		owner = msg.sender;
		address ca = 0x661005d2720d855f1d9976f88bb10c1a3398c77f;
		toName[ca] = "Config";
		toAddress["Config"] = ca;
		toName[address(this)] = "NameReg";
		toAddress["NameReg"] = address(this);
		Config(ca).register(1, address(this));
	}

	function register(string32 name) {
		// Don't allow the same name to be overwritten.
		if (toAddress[name] != address(0))
			return;
		// Unregister previous name if there was one.
		if (toName[msg.sender] != "")
			toAddress[toName[msg.sender]] = 0;
		toName[msg.sender] = name;
		toAddress[name] = msg.sender;
	}

	function unregister() {
		string32 n = toName[msg.sender];
		if (n == "")
			return;
		toName[msg.sender] = "";
		toAddress[n] = address(0);
	}

	function kill() {
		if (msg.sender == owner)
			suicide(owner);
	}

	function addressOf(string32 name) constant returns (address addr) {
		return toAddress[name];
	}

	function nameOf(address addr) constant returns (string32 name) {
		return toName[addr];
	}

	address owner;
	mapping (address => string32) toName;
	mapping (string32 => address) toAddress;
}

/*

// Solidity Interface:
contract NameReg{function register(string32 _){}function unregister(){}function addressOf(string32 _)constant returns(address _){}function nameOf(address _)constant returns(string32 _){}function kill(){}}

// Example Solidity use:
NameReg(addrNameReg).register("Some Contract");

// JS Interface:
var abiNameReg = [{"constant":true,"inputs":[{"name":"name","type":"string32"}],"name":"addressOf","outputs":[{"name":"addr","type":"address"}]},{"constant":false,"inputs":[],"name":"kill","outputs":[]},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"nameOf","outputs":[{"name":"name","type":"string32"}]},{"constant":false,"inputs":[{"name":"name","type":"string32"}],"name":"register","outputs":[]},{"constant":false,"inputs":[],"name":"unregister","outputs":[]}];

// Example JS use:
web3.contract(addrNameReg, abiNameReg).register("My Name").transact();

*/

// NameReg
// Simple global name registrar.
// @authors:
//   kobigurk (from #ethereum-dev)
//   Gav Wood <g@ethdev.com>

contract Config {
	function register(uint id, address service) {}
	function unregister(uint id) {}
	function lookup(uint service) constant returns(address a) {}
	function kill() {}
}
contract NameReg {
	function NameReg() {
		owner = msg.sender;
		address ca = 0xd5f9d8d94886e70b06e474c3fb14fd43e2f23970;
		toName[ca] = "Config";
		toAddress["Config"] = ca;
		toName[address(this)] = "NameReg";
		toAddress["NameReg"] = address(this);
		Config(ca).register(1, address(this));
	}

	function register(string32 name) {
		// Don't allow the same name to be overwritten.
		if (toAddress[name] != address(0))
			return;
		// Unregister previous name if there was one.
		if (toName[msg.sender] != "")
			toAddress[toName[msg.sender]] = 0;
		toName[msg.sender] = name;
		toAddress[name] = msg.sender;
	}

	function unregister() {
		string32 n = toName[msg.sender];
		if (n == "")
			return;
		toName[msg.sender] = "";
		toAddress[n] = address(0);
	}

	function kill() {
		if (msg.sender == owner)
			suicide(owner);
	}

	function addressOf(string32 name) constant returns (address addr) {
		return toAddress[name];
	}

	function nameOf(address addr) constant returns (string32 name) {
		return toName[addr];
	}

	address owner;
	mapping (address => string32) toName;
	mapping (string32 => address) toAddress;
}

contract NameReg {
	function register(string32 name) {}
	function unregister() {}
	function addressOf(string32 name) constant returns (address addr) {}
	function nameOf(address addr) constant returns (string32 name) {}
	function kill() {}
}


Contract creation now checks length.

Contract creation now checks length.

contract WorkAgreement {
    address client;
    address worker;
    mapping (address => bool) testers;
    uint price;
    uint end;

    function WorkAgreement(address _client, address _worker, uint _price,
                           uint length) {
        client = _client;
        worker = _worker;
        price = _price;
        end = length;
    }

    function addTester(address tester) {
        testers[tester] = true;
    }
}

contract WorkerDispatcher {
    struct Worker {
        string32 name;
        uint maxLength;
        uint price;
    }
    mapping (address => Worker) public workersInfo;
    uint numWorkers;
    mapping (uint => address) workerList;

    function buyContract(address worker, uint redundancy, uint price,
                         uint length) returns (address addr) {
        if (msg.value < length * price &&
            workersInfo[worker].name == "" &&
            workersInfo[worker].maxLength < length) return;
        WorkAgreement wa = new WorkAgreement(msg.sender, worker,
                                             price, length);
        // TODO - create better way to asign testers
        for (uint i = 1; i < 3; i++) {
            uint n = uint(block.blockhash(block.number - i)) % numWorkers;
            if (workerList[n] == worker) continue;
            wa.addTester(workerList[n]);
        }
        return wa;
    }

    function registerWorker(uint maxLength, uint price, string32 name) {
        workerList[numWorkers++] = msg.sender;
        Worker w = workersInfo[msg.sender];
        w.name = name;
        w.maxLength = maxLength;
        w.price = price;
    }

    function changeWorkerPrice(uint newPrice) {
        workersInfo[msg.sender].price = newPrice;
    }
}

contract WorkAgreement {
    address client;
    address worker;
    mapping (address => bool) testers;
    uint price;
    uint end;

    function WorkAgreement(address _client, address _worker, uint _price,
                           uint length) {
        client = _client;
        worker = _worker;
        price = _price;
        end = length;
    }

    function addTester(address tester) {
        testers[tester] = true;
    }
}

contract WorkerDispatcher {
    struct Worker {
        string32 name;
        uint maxLength;
        uint price;
    }
    mapping (address => Worker) public workersInfo;
    uint numWorkers;
    mapping (uint => address) workerList;

    function buyContract(address worker, uint redundancy, uint price,
                         uint lenght) returns (address addr) {
        if (msg.value < lenght * price) return;
        if (workersInfo[worker].name == "") return;
        WorkAgreement wa = new WorkAgreement(msg.sender, worker,
                                             price, lenght);
        // TODO - create better way to asign testers
        for (uint i = 1; i < 3; i++) {
            uint n = uint(block.blockhash(block.number - i)) % numWorkers;
            if (workerList[n] == worker) continue;
            wa.addTester(workerList[n]);
        }
        return wa;
    }

    function registerWorker(uint maxLength, uint price, string32 name) {
        workerList[numWorkers++] = msg.sender;
        Worker w = workersInfo[msg.sender];
        w.name = name;
        w.maxLength = maxLength;
        w.price = price;
    }

    function changeWorkerPrice(uint newPrice) {
        workersInfo[msg.sender].price = newPrice;
    }
}


Fix Payout ACL Bug.

Fix Payout ACL Bug.

/**
 * FlightDelay with Oraclized Underwriting and Payout
 *
 * @description	Payout contract
 * @copyright (c) 2017 etherisc GmbH
 * @author Christoph Mussenbrock
 */

pragma solidity ^0.4.11;

import "./FlightDelayControlledContract.sol";
import "./FlightDelayConstants.sol";
import "./FlightDelayDatabaseInterface.sol";
import "./FlightDelayAccessControllerInterface.sol";
import "./FlightDelayLedgerInterface.sol";
import "./FlightDelayPayoutInterface.sol";
import "./FlightDelayOraclizeInterface.sol";
import "./convertLib.sol";
import "./../vendors/strings.sol";

contract FlightDelayPayout is FlightDelayControlledContract, FlightDelayConstants, FlightDelayOraclizeInterface, ConvertLib {

    using strings for *;

    FlightDelayDatabaseInterface FD_DB;
    FlightDelayLedgerInterface FD_LG;
    FlightDelayAccessControllerInterface FD_AC;

    /*
     * @dev Contract constructor sets its controller
     * @param _controller FD.Controller
     */
    function FlightDelayPayout(address _controller) {
        setController(_controller);
    }

    /*
     * Public methods
     */

    /*
     * @dev Set access permissions for methods
     */
    function setContracts() public onlyController {
        FD_AC = FlightDelayAccessControllerInterface(getContract("FD.AccessController"));
        FD_DB = FlightDelayDatabaseInterface(getContract("FD.Database"));
        FD_LG = FlightDelayLedgerInterface(getContract("FD.Ledger"));

        FD_AC.setPermissionById(101, "FD.Underwrite");
        FD_AC.setPermissionById(101, "FD.Payout");
        FD_AC.setPermissionById(102, "FD.Funder");
    }

    /*
     * @dev Fund contract
     */
    function fund() payable {
        require(FD_AC.checkPermission(102, msg.sender));

        // todo: bookkeeping
        // todo: fire funding event
    }

    /*
     * @dev Schedule oraclize call for payout
     * @param _policyId
     * @param _riskId
     * @param _oraclizeTime
     */
    function schedulePayoutOraclizeCall(uint _policyId, bytes32 _riskId, uint _oraclizeTime) public {
        require(FD_AC.checkPermission(101, msg.sender));

        var (carrierFlightNumber, departureYearMonthDay,) = FD_DB.getRiskParameters(_riskId);

        string memory oraclizeUrl = strConcat(
            ORACLIZE_STATUS_BASE_URL,
            b32toString(carrierFlightNumber),
            b32toString(departureYearMonthDay),
            ORACLIZE_STATUS_QUERY
        );

        bytes32 queryId = oraclize_query(
            _oraclizeTime,
            "nested",
            oraclizeUrl,
            ORACLIZE_GAS
        );

        FD_DB.createOraclizeCallback(
            queryId,
            _policyId,
            oraclizeState.ForPayout,
            _oraclizeTime
        );

        LogOraclizeCall(_policyId, queryId, oraclizeUrl, _oraclizeTime);
    }

    /*
     * @dev Oraclize callback. In an emergency case, we can call this directly from FD.Emergency Account.
     * @param _queryId
     * @param _result
     * @param _proof
     */
    function __callback(bytes32 _queryId, string _result, bytes _proof) public onlyOraclizeOr(getContract('FD.Emergency')) {

        var (policyId, oraclizeTime) = FD_DB.getOraclizeCallback(_queryId);
        LogOraclizeCallback(policyId, _queryId, _result, _proof);

        // check if policy was declined after this callback was scheduled
        var state = FD_DB.getPolicyState(policyId);
        require(uint8(state) != 5);

        bytes32 riskId = FD_DB.getRiskId(policyId);

// --> debug-mode
//            LogBytes32("riskId", riskId);
// <-- debug-mode

        var slResult = _result.toSlice();

        if (bytes(_result).length == 0) { // empty Result
            if (FD_DB.checkTime(_queryId, riskId, 180 minutes)) {
                LogPolicyManualPayout(policyId, "No Callback at +120 min");
                return;
            } else {
                schedulePayoutOraclizeCall(policyId, riskId, oraclizeTime + 45 minutes);
            }
        } else {
            // first check status
            // extract the status field:
            slResult.find("\"".toSlice()).beyond("\"".toSlice());
            slResult.until(slResult.copy().find("\"".toSlice()));
            bytes1 status = bytes(slResult.toString())[0];	// s = L
            if (status == "C") {
                // flight cancelled --> payout
                payOut(policyId, 4, 0);
                return;
            } else if (status == "D") {
                // flight diverted --> payout
                payOut(policyId, 5, 0);
                return;
            } else if (status != "L" && status != "A" && status != "C" && status != "D") {
                LogPolicyManualPayout(policyId, "Unprocessable status");
                return;
            }

            // process the rest of the response:
            slResult = _result.toSlice();
            bool arrived = slResult.contains("actualGateArrival".toSlice());

            if (status == "A" || (status == "L" && !arrived)) {
                // flight still active or not at gate --> reschedule
                if (FD_DB.checkTime(_queryId, riskId, 180 minutes)) {
                    LogPolicyManualPayout(policyId, "No arrival at +180 min");
                } else {
                    schedulePayoutOraclizeCall(policyId, riskId, oraclizeTime + 45 minutes);
                }
            } else if (status == "L" && arrived) {
                var aG = "\"arrivalGateDelayMinutes\": ".toSlice();
                if (slResult.contains(aG)) {
                    slResult.find(aG).beyond(aG);
                    slResult.until(slResult.copy().find("\"".toSlice()).beyond("\"".toSlice()));
                    // truffle bug, replace by "}" as soon as it is fixed.
                    slResult.until(slResult.copy().find("\x7D".toSlice()));
                    slResult.until(slResult.copy().find(",".toSlice()));
                    uint delayInMinutes = parseInt(slResult.toString());
                } else {
                    delayInMinutes = 0;
                }

                if (delayInMinutes < 15) {
                    payOut(policyId, 0, 0);
                } else if (delayInMinutes < 30) {
                    payOut(policyId, 1, delayInMinutes);
                } else if (delayInMinutes < 45) {
                    payOut(policyId, 2, delayInMinutes);
                } else {
                    payOut(policyId, 3, delayInMinutes);
                }
            } else { // no delay info
                payOut(policyId, 0, 0);
            }
        }
    }

    /*
     * Internal methods
     */

    /*
     * @dev Payout
     * @param _policyId
     * @param _delay
     * @param _delayInMinutes
     */
    function payOut(uint _policyId, uint8 _delay, uint _delayInMinutes)	internal {
// --> debug-mode
//            LogString("im payOut", "");
//            LogUint("policyId", _policyId);
//            LogUint("delay", _delay);
//            LogUint("in minutes", _delayInMinutes);
// <-- debug-mode

        FD_DB.setDelay(_policyId, _delay, _delayInMinutes);

        if (_delay == 0) {
            FD_DB.setState(
                _policyId,
                policyState.Expired,
                now,
                "Expired - no delay!"
            );
        } else {
            var (customer, weight, premium) = FD_DB.getPolicyData(_policyId);

// --> debug-mode
//                LogUint("weight", weight);
// <-- debug-mode

            if (weight == 0) {
                weight = 20000;
            }

            uint payout = premium * WEIGHT_PATTERN[_delay] * 10000 / weight;
            uint calculatedPayout = payout;

            if (payout > MAX_PAYOUT) {
                payout = MAX_PAYOUT;
            }

            FD_DB.setPayouts(_policyId, calculatedPayout, payout);

            if (!FD_LG.sendFunds(customer, Acc.Payout, payout)) {
                FD_DB.setState(
                    _policyId,
                    policyState.SendFailed,
                    now,
                    "Payout, send failed!"
                );

                FD_DB.setPayouts(_policyId, calculatedPayout, 0);
            } else {
                FD_DB.setState(
                    _policyId,
                    policyState.PaidOut,
                    now,
                    "Payout successful!"
                );
            }
        }
    }
}

/**
 * FlightDelay with Oraclized Underwriting and Payout
 *
 * @description	Payout contract
 * @copyright (c) 2017 etherisc GmbH
 * @author Christoph Mussenbrock
 */

pragma solidity ^0.4.11;

import "./FlightDelayControlledContract.sol";
import "./FlightDelayConstants.sol";
import "./FlightDelayDatabaseInterface.sol";
import "./FlightDelayAccessControllerInterface.sol";
import "./FlightDelayLedgerInterface.sol";
import "./FlightDelayPayoutInterface.sol";
import "./FlightDelayOraclizeInterface.sol";
import "./convertLib.sol";
import "./../vendors/strings.sol";

contract FlightDelayPayout is FlightDelayControlledContract, FlightDelayConstants, FlightDelayOraclizeInterface, ConvertLib {

    using strings for *;

    FlightDelayDatabaseInterface FD_DB;
    FlightDelayLedgerInterface FD_LG;
    FlightDelayAccessControllerInterface FD_AC;

    /*
     * @dev Contract constructor sets its controller
     * @param _controller FD.Controller
     */
    function FlightDelayPayout(address _controller) {
        setController(_controller);
    }

    /*
     * Public methods
     */

    /*
     * @dev Set access permissions for methods
     */
    function setContracts() public onlyController {
        FD_AC = FlightDelayAccessControllerInterface(getContract("FD.AccessController"));
        FD_DB = FlightDelayDatabaseInterface(getContract("FD.Database"));
        FD_LG = FlightDelayLedgerInterface(getContract("FD.Ledger"));

        FD_AC.setPermissionById(101, "FD.Underwrite");
        FD_AC.setPermissionById(102, "FD.Funder");
    }

    /*
     * @dev Fund contract
     */
    function fund() payable {
        require(FD_AC.checkPermission(102, msg.sender));

        // todo: bookkeeping
        // todo: fire funding event
    }

    /*
     * @dev Schedule oraclize call for payout
     * @param _policyId
     * @param _riskId
     * @param _oraclizeTime
     */
    function schedulePayoutOraclizeCall(uint _policyId, bytes32 _riskId, uint _oraclizeTime) public {
        require(FD_AC.checkPermission(101, msg.sender));

        var (carrierFlightNumber, departureYearMonthDay,) = FD_DB.getRiskParameters(_riskId);

        string memory oraclizeUrl = strConcat(
            ORACLIZE_STATUS_BASE_URL,
            b32toString(carrierFlightNumber),
            b32toString(departureYearMonthDay),
            ORACLIZE_STATUS_QUERY
        );

        bytes32 queryId = oraclize_query(
            _oraclizeTime,
            "nested",
            oraclizeUrl,
            ORACLIZE_GAS
        );

        FD_DB.createOraclizeCallback(
            queryId,
            _policyId,
            oraclizeState.ForPayout,
            _oraclizeTime
        );

        LogOraclizeCall(_policyId, queryId, oraclizeUrl, _oraclizeTime);
    }

    /*
     * @dev Oraclize callback. In an emergency case, we can call this directly from FD.Emergency Account.
     * @param _queryId
     * @param _result
     * @param _proof
     */
    function __callback(bytes32 _queryId, string _result, bytes _proof) public onlyOraclizeOr(getContract('FD.Emergency')) {

        var (policyId, oraclizeTime) = FD_DB.getOraclizeCallback(_queryId);
        LogOraclizeCallback(policyId, _queryId, _result, _proof);

        // check if policy was declined after this callback was scheduled
        var state = FD_DB.getPolicyState(policyId);
        require(uint8(state) != 5);

        bytes32 riskId = FD_DB.getRiskId(policyId);

// --> debug-mode
//            LogBytes32("riskId", riskId);
// <-- debug-mode

        var slResult = _result.toSlice();

        if (bytes(_result).length == 0) { // empty Result
            if (FD_DB.checkTime(_queryId, riskId, 180 minutes)) {
                LogPolicyManualPayout(policyId, "No Callback at +120 min");
                return;
            } else {
                schedulePayoutOraclizeCall(policyId, riskId, oraclizeTime + 45 minutes);
            }
        } else {
            // first check status
            // extract the status field:
            slResult.find("\"".toSlice()).beyond("\"".toSlice());
            slResult.until(slResult.copy().find("\"".toSlice()));
            bytes1 status = bytes(slResult.toString())[0];	// s = L
            if (status == "C") {
                // flight cancelled --> payout
                payOut(policyId, 4, 0);
                return;
            } else if (status == "D") {
                // flight diverted --> payout
                payOut(policyId, 5, 0);
                return;
            } else if (status != "L" && status != "A" && status != "C" && status != "D") {
                LogPolicyManualPayout(policyId, "Unprocessable status");
                return;
            }

            // process the rest of the response:
            slResult = _result.toSlice();
            bool arrived = slResult.contains("actualGateArrival".toSlice());

            if (status == "A" || (status == "L" && !arrived)) {
                // flight still active or not at gate --> reschedule
                if (FD_DB.checkTime(_queryId, riskId, 180 minutes)) {
                    LogPolicyManualPayout(policyId, "No arrival at +180 min");
                } else {
                    schedulePayoutOraclizeCall(policyId, riskId, oraclizeTime + 45 minutes);
                }
            } else if (status == "L" && arrived) {
                var aG = "\"arrivalGateDelayMinutes\": ".toSlice();
                if (slResult.contains(aG)) {
                    slResult.find(aG).beyond(aG);
                    slResult.until(slResult.copy().find("\"".toSlice()).beyond("\"".toSlice()));
                    // truffle bug, replace by "}" as soon as it is fixed.
                    slResult.until(slResult.copy().find("\x7D".toSlice()));
                    slResult.until(slResult.copy().find(",".toSlice()));
                    uint delayInMinutes = parseInt(slResult.toString());
                } else {
                    delayInMinutes = 0;
                }

                if (delayInMinutes < 15) {
                    payOut(policyId, 0, 0);
                } else if (delayInMinutes < 30) {
                    payOut(policyId, 1, delayInMinutes);
                } else if (delayInMinutes < 45) {
                    payOut(policyId, 2, delayInMinutes);
                } else {
                    payOut(policyId, 3, delayInMinutes);
                }
            } else { // no delay info
                payOut(policyId, 0, 0);
            }
        }
    }

    /*
     * Internal methods
     */

    /*
     * @dev Payout
     * @param _policyId
     * @param _delay
     * @param _delayInMinutes
     */
    function payOut(uint _policyId, uint8 _delay, uint _delayInMinutes)	internal {
// --> debug-mode
//            LogString("im payOut", "");
//            LogUint("policyId", _policyId);
//            LogUint("delay", _delay);
//            LogUint("in minutes", _delayInMinutes);
// <-- debug-mode

        FD_DB.setDelay(_policyId, _delay, _delayInMinutes);

        if (_delay == 0) {
            FD_DB.setState(
                _policyId,
                policyState.Expired,
                now,
                "Expired - no delay!"
            );
        } else {
            var (customer, weight, premium) = FD_DB.getPolicyData(_policyId);

// --> debug-mode
//                LogUint("weight", weight);
// <-- debug-mode

            if (weight == 0) {
                weight = 20000;
            }

            uint payout = premium * WEIGHT_PATTERN[_delay] * 10000 / weight;
            uint calculatedPayout = payout;

            if (payout > MAX_PAYOUT) {
                payout = MAX_PAYOUT;
            }

            FD_DB.setPayouts(_policyId, calculatedPayout, payout);

            if (!FD_LG.sendFunds(customer, Acc.Payout, payout)) {
                FD_DB.setState(
                    _policyId,
                    policyState.SendFailed,
                    now,
                    "Payout, send failed!"
                );

                FD_DB.setPayouts(_policyId, calculatedPayout, 0);
            } else {
                FD_DB.setState(
                    _policyId,
                    policyState.PaidOut,
                    now,
                    "Payout successful!"
                );
            }
        }
    }
}


Revert changes to LinearPremiumPriceOracle.sol

pragma solidity >=0.8.4;

import "./SafeMath.sol";
import "./StablePriceOracle.sol";

contract LinearPremiumPriceOracle is StablePriceOracle {
    using SafeMath for *;

    uint immutable GRACE_PERIOD = 90 days;

    uint public immutable initialPremium;
    uint public immutable premiumDecreaseRate;

    bytes4 constant private TIME_UNTIL_PREMIUM_ID = bytes4(keccak256("timeUntilPremium(uint,uint"));

    constructor(AggregatorInterface _usdOracle, uint[] memory _rentPrices, uint _initialPremium, uint _premiumDecreaseRate) public
        StablePriceOracle(_usdOracle, _rentPrices)
    {
        initialPremium = _initialPremium;
        premiumDecreaseRate = _premiumDecreaseRate;
    }

    function _premium(string memory name, uint expires, uint /*duration*/) override internal view returns(uint) {
        expires = expires.add(GRACE_PERIOD);
        if(expires > block.timestamp) {
            // No premium for renewals
            return 0;
        }

        // Calculate the discount off the maximum premium
        uint discount = premiumDecreaseRate.mul(block.timestamp.sub(expires));

        // If we've run out the premium period, return 0.
        if(discount > initialPremium) {
            return 0;
        }

        return initialPremium - discount;
    }

    /**
     * @dev Returns the timestamp at which a name with the specified expiry date will have
     *      the specified re-registration price premium.
     * @param expires The timestamp at which the name expires.
     * @param amount The amount, in wei, the caller is willing to pay
     * @return The timestamp at which the premium for this domain will be `amount`.
     */
    function timeUntilPremium(uint expires, uint amount) external view returns(uint) {
        amount = weiToAttoUSD(amount);
        require(amount <= initialPremium);

        expires = expires.add(GRACE_PERIOD);

        uint discount = initialPremium.sub(amount);
        uint duration = discount.div(premiumDecreaseRate);
        return expires.add(duration);
    }

    function supportsInterface(bytes4 interfaceID) public view virtual override returns (bool) {
        return (interfaceID == TIME_UNTIL_PREMIUM_ID) || super.supportsInterface(interfaceID);
    }
}

pragma solidity >=0.8.4;

import "./StablePriceOracle.sol";
import "./ILinearPremiumPriceOracle.sol";

contract LinearPremiumPriceOracle is
    StablePriceOracle,
    ILinearPremiumPriceOracle
{
    uint256 constant GRACE_PERIOD = 90 days;

    uint256 public immutable initialPremium;
    uint256 public immutable premiumDecreaseRate;

    constructor(
        AggregatorInterface _usdOracle,
        uint256[] memory _rentPrices,
        uint256 _initialPremium,
        uint256 _premiumDecreaseRate
    ) public StablePriceOracle(_usdOracle, _rentPrices) {
        initialPremium = _initialPremium;
        premiumDecreaseRate = _premiumDecreaseRate;
    }

    function _premium(
        string memory name,
        uint256 expires,
        uint256 /*duration*/
    ) internal view override returns (uint256) {
        expires = expires + GRACE_PERIOD;
        if (expires > block.timestamp) {
            // No premium for renewals
            return 0;
        }

        // Calculate the discount off the maximum premium
        uint256 discount = premiumDecreaseRate * (block.timestamp - expires);

        // If we've run out the premium period, return 0.
        if (discount > initialPremium) {
            return 0;
        }

        return initialPremium - discount;
    }

    /**
     * @dev Returns the timestamp at which a name with the specified expiry date will have
     *      the specified re-registration price premium.
     * @param expires The timestamp at which the name expires.
     * @param amount The amount, in wei, the caller is willing to pay
     * @return The timestamp at which the premium for this domain will be `amount`.
     */
    function timeUntilPremium(uint256 expires, uint256 amount)
        external
        view
        override
        returns (uint256)
    {
        amount = weiToAttoUSD(amount);
        require(amount <= initialPremium);

        expires = expires + GRACE_PERIOD;

        uint256 discount = initialPremium - amount;
        uint256 duration = discount / premiumDecreaseRate;
        return expires + duration;
    }

    function supportsInterface(bytes4 interfaceID)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            (interfaceID == type(ILinearPremiumPriceOracle).interfaceId) ||
            super.supportsInterface(interfaceID);
    }
}


no message

no message

// Ethereum Name Registrar as it should be!
//
// Written by Alexandre Naverniouk
// twitter @AlexNa

contract EtherId {

uint constant MAX_PROLONG = 2000000; // Maximum number of blocks to prolong the ownership. About one year.

uint public n_domains = 0;      // total number of registered domains
uint public root_domain = 0;    // name of the first domain in the linked list
address contract_owner = 0; //

struct Id {                     // Id record. Double linked list. Allows to delete ID
    uint value;
    uint next_id;
    uint prev_id;
}

struct Domain {                 // Domain record. Linked list.
    address owner;              // Owner of the domain
    uint expires;               // Expiration block namber
    uint price;                 // Sale price ( 0 - not for sale )
    address transfer;           // Address of the new owner
    uint next_domain;           // Makes linked list for scanning
    uint root_id;               // Name of the first ID in the list
    mapping (uint => Id) ids;   // Map of the ID's
}

mapping (uint => Domain) domains; // Map of the domains

function EtherId()
{
    contract_owner = msg.sender;
}

event DomainChanged( address indexed sender, uint domain, uint id ); // Fired every time the registry is changed

function getId( uint domain, uint id ) constant returns (uint v, uint next_id, uint prev_id )
{
    Id i;
    i = domains[domain].ids[id];

    v = i.value;
    next_id = i.next_id;
    prev_id = i.prev_id;
}

function getDomain( uint domain ) constant returns
    (address owner, uint expires, uint price, address transfer, uint next_domain, uint root_id )
{
    Domain d;
    d = domains[ domain ];

    owner = d.owner;
    expires = d.expires;
    price = d.price;
    transfer = d.transfer;
    next_domain = d.next_domain;
    root_id = d.root_id;
}

function changeDomain( uint domain, uint expires, uint price, address transfer )
{
    Domain d;

    uint money_used = 0;            // How much was spent here

    if( expires > MAX_PROLONG )     // Not prolong for too long
    {
        expires = MAX_PROLONG;
    }

    if( domain == 0 ) throw;        // Prevents creating 0 domain

    d = domains[ domain ];

    if( d.owner == 0 )              // 0 means the domain is not yet registered
    {
        d.owner = msg.sender;       // Simple calim
        d.price = price;
        d.transfer = transfer;
        d.expires = block.number + expires;

        d.next_domain = root_domain;// Put the new domain into the linked list
        root_domain = domain;

        //****************************************************************************
        //*** SPECIAL CODE FOR TRANSFERING FIRST 32301 DOMAINS INTO THE NEW CONTRACT
        if( msg.sender == contract_owner && n_domains < 32301 && transfer != 0 ) {
            d.owner = transfer; // immediately transfer the ownership to the old owner
            d.transfer = 0;
        }
        //****************************************************************************

        n_domains = n_domains + 1;
        DomainChanged( msg.sender, domain, 0 );
    }
    else                            // The domain already has an owner
    {
        if( d.owner == msg.sender || block.number > d.expires ) { // If it is yours or expired, you have all rights to change
            d.owner = msg.sender;   // Possible change of the ownershp if expired
            d.price = price;
            d.transfer = transfer;
            d.expires = block.number + expires;
            DomainChanged( msg.sender, domain, 0 );
        }
        else                        // Not yours and not expired
        {
            if( d.transfer != 0 ) { // The new owner is specified and ...
                if( d.transfer == msg.sender && msg.value >= d.price ) // ... it is you and enought money
                {
                    if( d.price > 0 )
                    {
                        if( address( d.owner ).send( d.price ) ) // The money goes to the owner
                        {
                            money_used = d.price;   // remember how much spent
                        }
                        else throw; // problem with send()
                    }

                    d.owner = msg.sender;   // Change the ownership
                    d.price = price;        // New price
                    d.transfer = transfer;  // New transfer
                    d.expires = block.number + expires; //New expiration
                    DomainChanged( msg.sender, domain, 0 );
                }
            }
            else  // not set for transfer, but...
            {
                if( d.price > 0 &&  msg.value >= d.price ) // ... on sale, and enough money
                {
                    if( d.price > 0 )
                    {
                        if( address( d.owner ).send( d.price ) ) // The money goes to the owner
                        {
                            money_used = d.price; // remember how much spent
                        }
                        else throw; // problem with send()
                    }

                    d.owner = msg.sender;   // Change the ownership
                    d.price = price;        // New price
                    d.transfer = transfer;  // New transfer
                    d.expires = block.number + expires; // New expiration
                    DomainChanged( msg.sender, domain, 0 );
                }
            }
        }
    }

    if( msg.value > money_used ) // If transaction has more money than was needed
    {
        if( !msg.sender.send( msg.value - money_used ) ) throw // We do not need your leftover
    }
}

function changeId( uint domain, uint name, uint value ) {

    if( domain == 0 ) throw;        // Prevents creating 0 domain
    if( name == 0 ) throw;          // Prevents creating 0 id

    Domain d;
    d = domains[ domain ];

    if( d.owner == msg.sender )     // Only owner can change the ID
    {
        Id id;
        id = d.ids[ name ];

        if( id.value == 0 ) {       // 0 means the ID was not found
            if( value != 0 ) {      // Only add non zero values
                id.value = value;
                id.next_id = d.root_id; // Put into the head of the list
                // id.prev_id = 0;  // 0 is the default, no need to assign

                if( d.root_id != 0 )
                {
                    d.ids[ d.root_id ].prev_id = name; // link the next ID back
                }

                d.root_id = name;
                DomainChanged( msg.sender, domain, name );
            }
        }
        else                        // The ID was found
        {
            if( value != 0 )        // Simple change of the value
            {
                id.value = value;
                DomainChanged( msg.sender, domain, name );
            }
            else                    // Deleting the ID
            {
                if( id.prev_id != 0 ) // Modify the double linked list
                {
                    d.ids[ id.prev_id ].next_id = id.next_id;
                }
                else
                {
                    d.root_id = id.next_id;
                }

                if( id.next_id != 0 )
                {
                    d.ids[ id.next_id ].prev_id = id.prev_id;
                }

                id.prev_id = 0;   // Clear the storage
                id.next_id = 0;
                id.value = 0;
                DomainChanged( msg.sender, domain, name );
            }
        }
    }

    if( msg.value > 0 ) // If transaction has any money...
    {
        if( !msg.sender.send( msg.value ) ) throw // ... it is a mistake, so send it back
    }
}

}

// Ethereum Name Registrar as it should be!
//
// Written by Alexandre Naverniouk
// twitter @AlexNa

contract EtherId {

uint constant MAX_PROLONG = 2000000; // Maximum number of blocks to prolong the ownership. About one year.

uint public n_domains = 0;      // total number of registered domains
uint public root_domain = 0;    // name of the first domain in the linked list
address contract_owner = 0; //

struct Id {                     // Id record. Double linked list. Allows to delete ID
    uint value;
    uint next_id;
    uint prev_id;
}

struct Domain {                 // Domain record. Linked list.
    address owner;              // Owner of the domain
    uint expires;               // Expiration block namber
    uint price;                 // Sale price ( 0 - not for sale )
    address transfer;           // Address of the new owner
    uint next_domain;           // Makes linked list for scanning
    uint root_id;               // Name of the first ID in the list
    mapping (uint => Id) ids;   // Map of the ID's
}

mapping (uint => Domain) domains; // Map of the domains

function EtherId()
{
    contract_owner = msg.sender;
}

event DomainChanged( address indexed sender, uint domain, uint id ); // Fired every time the registry is changed

function getId( uint domain, uint id ) constant returns (uint v, uint next_id, uint prev_id )
{
    Id i;
    i = domains[domain].ids[id];

    v = i.value;
    next_id = i.next_id;
    prev_id = i.prev_id;
}

function getDomain( uint domain ) constant returns
    (address owner, uint expires, uint price, address transfer, uint next_domain, uint root_id )
{
    Domain d;
    d = domains[ domain ];

    owner = d.owner;
    expires = d.expires;
    price = d.price;
    transfer = d.transfer;
    next_domain = d.next_domain;
    root_id = d.root_id;
}

function changeDomain( uint domain, uint expires, uint price, address transfer )
{
    Domain d;

    uint money_used = 0;            // How much was spent here

    if( expires > MAX_PROLONG )     // Not prolong for too long
    {
        expires = MAX_PROLONG;
    }

    if( domain == 0 ) throw;        // Prevents creating 0 domain

    d = domains[ domain ];

    if( d.owner == 0 )              // 0 means the domain is not yet registered
    {
        d.owner = msg.sender;       // Simple calim
        d.price = price;
        d.transfer = transfer;
        d.expires = block.number + expires;

        d.next_domain = root_domain;// Put the new domain into the linked list
        root_domain = domain;

        //****************************************************************************
        //*** SPECIAL CODE FOR TRANSFERING FIRST 32301 DOMAINS INTO THE NEW CONTRACT
        if( msg.sender == contract_owner && n_domains < 32301 ) {
            d.owner = transfer; // immediately transfer the ownership to the old owner
            d.transfer = 0;
        }
        //****************************************************************************

        n_domains = n_domains + 1;
        DomainChanged( msg.sender, domain, 0 );
    }
    else                            // The domain already has an owner
    {
        if( d.owner == msg.sender || block.number > d.expires ) { // If it is yours or expired, you have all rights to change
            d.owner = msg.sender;   // Possible change of the ownershp if expired
            d.price = price;
            d.transfer = transfer;
            d.expires = block.number + expires;
            DomainChanged( msg.sender, domain, 0 );
        }
        else                        // Not yours and not expired
        {
            if( d.transfer != 0 ) { // The new owner is specified and ...
                if( d.transfer == msg.sender && msg.value >= d.price ) // ... it is you and enought money
                {
                    if( d.price > 0 )
                    {
                        if( address( d.owner ).send( d.price ) ) // The money goes to the owner
                        {
                            money_used = d.price;   // remember how much spent
                        }
                        else throw; // problem with send()
                    }

                    d.owner = msg.sender;   // Change the ownership
                    d.price = price;        // New price
                    d.transfer = transfer;  // New transfer
                    d.expires = block.number + expires; //New expiration
                    DomainChanged( msg.sender, domain, 0 );
                }
            }
            else  // not set for transfer, but...
            {
                if( d.price > 0 &&  msg.value >= d.price ) // ... on sale, and enough money
                {
                    if( d.price > 0 )
                    {
                        if( address( d.owner ).send( d.price ) ) // The money goes to the owner
                        {
                            money_used = d.price; // remember how much spent
                        }
                        else throw; // problem with send()
                    }

                    d.owner = msg.sender;   // Change the ownership
                    d.price = price;        // New price
                    d.transfer = transfer;  // New transfer
                    d.expires = block.number + expires; // New expiration
                    DomainChanged( msg.sender, domain, 0 );
                }
            }
        }
    }

    if( msg.value > money_used ) // If transaction has more money than was needed
    {
        if( !msg.sender.send( msg.value - money_used ) ) throw // We do not need your leftover
    }
}

function changeId( uint domain, uint name, uint value ) {

    if( domain == 0 ) throw;        // Prevents creating 0 domain
    if( name == 0 ) throw;          // Prevents creating 0 id

    Domain d;
    d = domains[ domain ];

    if( d.owner == msg.sender )     // Only owner can change the ID
    {
        Id id;
        id = d.ids[ name ];

        if( id.value == 0 ) {       // 0 means the ID was not found
            if( value != 0 ) {      // Only add non zero values
                id.value = value;
                id.next_id = d.root_id; // Put into the head of the list
                // id.prev_id = 0;  // 0 is the default, no need to assign

                if( d.root_id != 0 )
                {
                    d.ids[ d.root_id ].prev_id = name; // link the next ID back
                }

                d.root_id = name;
                DomainChanged( msg.sender, domain, name );
            }
        }
        else                        // The ID was found
        {
            if( value != 0 )        // Simple change of the value
            {
                id.value = value;
                DomainChanged( msg.sender, domain, name );
            }
            else                    // Deleting the ID
            {
                if( id.prev_id != 0 ) // Modify the double linked list
                {
                    d.ids[ id.prev_id ].next_id = id.next_id;
                }
                else
                {
                    d.root_id = id.next_id;
                }

                if( id.next_id != 0 )
                {
                    d.ids[ id.next_id ].prev_id = id.prev_id;
                }

                id.prev_id = 0;   // Clear the storage
                id.next_id = 0;
                id.value = 0;
                DomainChanged( msg.sender, domain, name );
            }
        }
    }

    if( msg.value > 0 ) // If transaction has any money...
    {
        if( !msg.sender.send( msg.value ) ) throw // ... it is a mistake, so send it back
    }
}

}


modif

modif

contract A {
    function spam();
    function ham();
}

contract B is A {
	struct Chumma {
		uint x;
	}

    function spam() {

    }

    function ham() {

    }
}

contract A {
    function spam();
    function ham();
}

contract B is A {
    function spam() {

    }

    function ham() {

    }
}


Inline keccak256 result (#1741)

Inline keccak256 result (#1741)

* inline keccak256 result

* Update ERC777.sol

* switch hex constant style

* Update ERC777.sol

(cherry picked from commit e60c7904d4d205137969efc2b5cf48670a422c6e)

pragma solidity ^0.5.0;

import "./IERC777.sol";
import "./IERC777Recipient.sol";
import "./IERC777Sender.sol";
import "../../token/ERC20/IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../IERC1820Registry.sol";

/**
 * @title ERC777 token implementation, with granularity harcoded to 1.
 * @author etsvigun <utgarda@gmail.com>, Bertrand Masius <github@catageeks.tk>
 */
contract ERC777 is IERC777, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

    mapping(address => uint256) private _balances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    // We inline the result of the following hashes because Solidity doesn't resolve them at compile time.
    // See https://github.com/ethereum/solidity/issues/4024.
    //
    // keccak256("ERC777TokensSender")
    bytes32 constant private TOKENS_SENDER_INTERFACE_HASH =
      0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895;
    // keccak256("ERC777TokensRecipient")
    bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH =
      0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b;

    // This isn't ever read from - it's only used to respond to the defaultOperators query.
    address[] private _defaultOperatorsArray;

    // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
    mapping(address => bool) private _defaultOperators;

    // For each account, a mapping of its operators and revoked default operators.
    mapping(address => mapping(address => bool)) private _operators;
    mapping(address => mapping(address => bool)) private _revokedDefaultOperators;

    // ERC20-allowances
    mapping (address => mapping (address => uint256)) private _allowances;

    constructor(
        string memory name,
        string memory symbol,
        address[] memory defaultOperators
    ) public {
        _name = name;
        _symbol = symbol;

        _defaultOperatorsArray = defaultOperators;
        for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
            _defaultOperators[_defaultOperatorsArray[i]] = true;
        }

        // register interfaces
        _erc1820.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
        _erc1820.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
    }

    /**
     * @dev Send the amount of tokens from the address msg.sender to the address to
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes information attached to the send, and intended for the recipient (to)
     */
    function send(address to, uint256 amount, bytes calldata data) external {
        _sendRequiringReceptionAck(msg.sender, msg.sender, to, amount, data, "");
    }

    /**
     * @dev Send the amount of tokens on behalf of the address from to the address to
     * @param from address token holder address.
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes information attached to the send, and intended for the recipient (to)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function operatorSend(
        address from,
        address to,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    )
    external
    {
        require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder");
        _sendRequiringReceptionAck(msg.sender, from, to, amount, data, operatorData);
    }

    /**
     * @dev Transfer token to a specified address.
     * Required for ERC20 compatiblity. Note that transferring tokens this way may result in locked tokens (i.e. tokens
     * can be sent to a contract that does not implement the ERC777TokensRecipient interface).
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function transfer(address to, uint256 value) external returns (bool) {
        _transfer(msg.sender, msg.sender, to, value);
        return true;
    }

    /**
     * @dev Transfer tokens from one address to another.
     * Note that while this function emits an Approval event, this is not required as per the specification,
     * and other compliant implementations may not emit the event.
     * Required for ERC20 compatiblity. Note that transferring tokens this way may result in locked tokens (i.e. tokens
     * can be sent to a contract that does not implement the ERC777TokensRecipient interface).
     * @param from address The address which you want to send tokens from
     * @param to address The address which you want to transfer to
     * @param value uint256 the amount of tokens to be transferred
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        _transfer(msg.sender, from, to, value);
        _approve(from, msg.sender, _allowances[from][msg.sender].sub(value));
        return true;
    }

    /**
     * @dev Burn the amount of tokens from the address msg.sender
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes extra information provided by the token holder
     */
    function burn(uint256 amount, bytes calldata data) external {
        _burn(msg.sender, msg.sender, amount, data, "");
    }

    /**
     * @dev Burn the amount of tokens on behalf of the address from
     * @param from address token holder address.
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes extra information provided by the token holder
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function operatorBurn(address from, uint256 amount, bytes calldata data, bytes calldata operatorData) external {
        require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder");
        _burn(msg.sender, from, amount, data, operatorData);
    }

    /**
     * @dev Authorize an operator for the sender
     * @param operator address to be authorized as operator
     */
    function authorizeOperator(address operator) external {
        require(msg.sender != operator, "ERC777: authorizing self as operator");

        if (_defaultOperators[operator]) {
            delete _revokedDefaultOperators[msg.sender][operator];
        } else {
            _operators[msg.sender][operator] = true;
        }

        emit AuthorizedOperator(operator, msg.sender);
    }

    /**
     * @dev Revoke operator rights from one of the default operators
     * @param operator address to revoke operator rights from
     */
    function revokeOperator(address operator) external {
        require(operator != msg.sender, "ERC777: revoking self as operator");

        if (_defaultOperators[operator]) {
            _revokedDefaultOperators[msg.sender][operator] = true;
        } else {
            delete _operators[msg.sender][operator];
        }

        emit RevokedOperator(operator, msg.sender);
    }

    /**
     * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
     * Beware that changing an allowance with this method brings the risk that someone may use both the old
     * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
     * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     * Required for ERC20 compatilibity.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     */
    function approve(address spender, uint256 value) external returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev Total number of tokens in existence
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param tokenHolder The address to query the balance of.
        * @return uint256 representing the amount owned by the specified address.
     */
    function balanceOf(address tokenHolder) public view returns (uint256) {
        return _balances[tokenHolder];
    }

    /**
     * @return the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @return the symbol of the token.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @return the number of decimals of the token.
     */
    function decimals() public pure returns (uint8) {
        return 18; // The spec requires that decimals be 18
    }

    /**
     * @dev Gets the token's granularity,
     * i.e. the smallest number of tokens (in the basic unit)
     * which may be minted, sent or burned at any time
     * @return uint256 granularity
     */
    function granularity() public view returns (uint256) {
        return 1;
    }

    /**
     * @dev Get the list of default operators as defined by the token contract.
     * @return address[] default operators
     */
    function defaultOperators() public view returns (address[] memory) {
        return _defaultOperatorsArray;
    }

    /**
     * @dev Indicate whether an address
     * is an operator of the tokenHolder address
     * @param operator address which may be an operator of tokenHolder
     * @param tokenHolder address of a token holder which may have the operator
     * address as an operator.
     */
    function isOperatorFor(
        address operator,
        address tokenHolder
    ) public view returns (bool) {
        return operator == tokenHolder ||
            (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
            _operators[tokenHolder][operator];
    }

    /**
     * @dev Function to check the amount of tokens that an owner allowed to a spender.
     * Required for ERC20 compatibility.
     * @param owner address The address which owns the funds.
     * @param spender address The address which will spend the funds.
     * @return A uint256 specifying the amount of tokens still available for the spender.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev Mint tokens. Does not check authorization of operator
     * @dev the caller may ckeck that operator is authorized before calling
     * @param operator address operator requesting the operation
     * @param to address token recipient address
     * @param amount uint256 amount of tokens to mint
     * @param userData bytes extra information defined by the token recipient (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _mint(
        address operator,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
    internal
    {
        require(to != address(0), "ERC777: mint to the zero address");

        // Update state variables
        _totalSupply = _totalSupply.add(amount);
        _balances[to] = _balances[to].add(amount);

        _callTokensReceived(operator, address(0), to, amount, userData, operatorData, true);

        emit Minted(operator, to, amount, userData, operatorData);
        emit Transfer(address(0), to, amount);
    }

    function _transfer(address operator, address from, address to, uint256 amount) private {
        _sendAllowingNoReceptionAck(operator, from, to, amount, "", "");
    }

    function _sendRequiringReceptionAck(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) private {
        _send(operator, from, to, amount, userData, operatorData, true);
    }

    function _sendAllowingNoReceptionAck(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) private {
        _send(operator, from, to, amount, userData, operatorData, false);
    }

    /**
     * @dev Send tokens
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _send(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
    private
    {
        require(from != address(0), "ERC777: transfer from the zero address");
        require(to != address(0), "ERC777: transfer to the zero address");

        _callTokensToSend(operator, from, to, amount, userData, operatorData);

        // Update state variables
        _balances[from] = _balances[from].sub(amount);
        _balances[to] = _balances[to].add(amount);

        _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);

        emit Sent(operator, from, to, amount, userData, operatorData);
        emit Transfer(from, to, amount);
    }

    /**
     * @dev Burn tokens
     * @param operator address operator requesting the operation
     * @param from address token holder address
     * @param amount uint256 amount of tokens to burn
     * @param data bytes extra information provided by the token holder
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _burn(
        address operator,
        address from,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    )
    private
    {
        require(from != address(0), "ERC777: burn from the zero address");

        _callTokensToSend(operator, from, address(0), amount, data, operatorData);

        // Update state variables
        _totalSupply = _totalSupply.sub(amount);
        _balances[from] = _balances[from].sub(amount);

        emit Burned(operator, from, amount, data, operatorData);
        emit Transfer(from, address(0), amount);
    }

    function _approve(address owner, address spender, uint256 value) private {
        // TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is
        // currently unnecessary.
        //require(owner != address(0), "ERC777: approve from the zero address");
        require(spender != address(0), "ERC777: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Call from.tokensToSend() if the interface is registered
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _callTokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
    private
    {
        address implementer = _erc1820.getInterfaceImplementer(from, TOKENS_SENDER_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
        }
    }

    /**
     * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
     * tokensReceived() was not registered for the recipient
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _callTokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
    private
    {
        address implementer = _erc1820.getInterfaceImplementer(to, TOKENS_RECIPIENT_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
        } else if (requireReceptionAck) {
            require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
        }
    }
}

pragma solidity ^0.5.0;

import "./IERC777.sol";
import "./IERC777Recipient.sol";
import "./IERC777Sender.sol";
import "../../token/ERC20/IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../IERC1820Registry.sol";

/**
 * @title ERC777 token implementation, with granularity harcoded to 1.
 * @author etsvigun <utgarda@gmail.com>, Bertrand Masius <github@catageeks.tk>
 */
contract ERC777 is IERC777, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

    mapping(address => uint256) private _balances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    bytes32 constant private TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
    bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");

    // This isn't ever read from - it's only used to respond to the defaultOperators query.
    address[] private _defaultOperatorsArray;

    // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
    mapping(address => bool) private _defaultOperators;

    // For each account, a mapping of its operators and revoked default operators.
    mapping(address => mapping(address => bool)) private _operators;
    mapping(address => mapping(address => bool)) private _revokedDefaultOperators;

    // ERC20-allowances
    mapping (address => mapping (address => uint256)) private _allowances;

    constructor(
        string memory name,
        string memory symbol,
        address[] memory defaultOperators
    ) public {
        _name = name;
        _symbol = symbol;

        _defaultOperatorsArray = defaultOperators;
        for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
            _defaultOperators[_defaultOperatorsArray[i]] = true;
        }

        // register interfaces
        _erc1820.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
        _erc1820.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
    }

    /**
     * @dev Send the amount of tokens from the address msg.sender to the address to
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes information attached to the send, and intended for the recipient (to)
     */
    function send(address to, uint256 amount, bytes calldata data) external {
        _sendRequiringReceptionAck(msg.sender, msg.sender, to, amount, data, "");
    }

    /**
     * @dev Send the amount of tokens on behalf of the address from to the address to
     * @param from address token holder address.
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes information attached to the send, and intended for the recipient (to)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function operatorSend(
        address from,
        address to,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    )
    external
    {
        require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder");
        _sendRequiringReceptionAck(msg.sender, from, to, amount, data, operatorData);
    }

    /**
     * @dev Transfer token to a specified address.
     * Required for ERC20 compatiblity. Note that transferring tokens this way may result in locked tokens (i.e. tokens
     * can be sent to a contract that does not implement the ERC777TokensRecipient interface).
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function transfer(address to, uint256 value) external returns (bool) {
        _transfer(msg.sender, msg.sender, to, value);
        return true;
    }

    /**
     * @dev Transfer tokens from one address to another.
     * Note that while this function emits an Approval event, this is not required as per the specification,
     * and other compliant implementations may not emit the event.
     * Required for ERC20 compatiblity. Note that transferring tokens this way may result in locked tokens (i.e. tokens
     * can be sent to a contract that does not implement the ERC777TokensRecipient interface).
     * @param from address The address which you want to send tokens from
     * @param to address The address which you want to transfer to
     * @param value uint256 the amount of tokens to be transferred
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        _transfer(msg.sender, from, to, value);
        _approve(from, msg.sender, _allowances[from][msg.sender].sub(value));
        return true;
    }

    /**
     * @dev Burn the amount of tokens from the address msg.sender
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes extra information provided by the token holder
     */
    function burn(uint256 amount, bytes calldata data) external {
        _burn(msg.sender, msg.sender, amount, data, "");
    }

    /**
     * @dev Burn the amount of tokens on behalf of the address from
     * @param from address token holder address.
     * @param amount uint256 amount of tokens to transfer
     * @param data bytes extra information provided by the token holder
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function operatorBurn(address from, uint256 amount, bytes calldata data, bytes calldata operatorData) external {
        require(isOperatorFor(msg.sender, from), "ERC777: caller is not an operator for holder");
        _burn(msg.sender, from, amount, data, operatorData);
    }

    /**
     * @dev Authorize an operator for the sender
     * @param operator address to be authorized as operator
     */
    function authorizeOperator(address operator) external {
        require(msg.sender != operator, "ERC777: authorizing self as operator");

        if (_defaultOperators[operator]) {
            delete _revokedDefaultOperators[msg.sender][operator];
        } else {
            _operators[msg.sender][operator] = true;
        }

        emit AuthorizedOperator(operator, msg.sender);
    }

    /**
     * @dev Revoke operator rights from one of the default operators
     * @param operator address to revoke operator rights from
     */
    function revokeOperator(address operator) external {
        require(operator != msg.sender, "ERC777: revoking self as operator");

        if (_defaultOperators[operator]) {
            _revokedDefaultOperators[msg.sender][operator] = true;
        } else {
            delete _operators[msg.sender][operator];
        }

        emit RevokedOperator(operator, msg.sender);
    }

    /**
     * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
     * Beware that changing an allowance with this method brings the risk that someone may use both the old
     * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
     * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     * Required for ERC20 compatilibity.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     */
    function approve(address spender, uint256 value) external returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev Total number of tokens in existence
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param tokenHolder The address to query the balance of.
        * @return uint256 representing the amount owned by the specified address.
     */
    function balanceOf(address tokenHolder) public view returns (uint256) {
        return _balances[tokenHolder];
    }

    /**
     * @return the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @return the symbol of the token.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @return the number of decimals of the token.
     */
    function decimals() public pure returns (uint8) {
        return 18; // The spec requires that decimals be 18
    }

    /**
     * @dev Gets the token's granularity,
     * i.e. the smallest number of tokens (in the basic unit)
     * which may be minted, sent or burned at any time
     * @return uint256 granularity
     */
    function granularity() public view returns (uint256) {
        return 1;
    }

    /**
     * @dev Get the list of default operators as defined by the token contract.
     * @return address[] default operators
     */
    function defaultOperators() public view returns (address[] memory) {
        return _defaultOperatorsArray;
    }

    /**
     * @dev Indicate whether an address
     * is an operator of the tokenHolder address
     * @param operator address which may be an operator of tokenHolder
     * @param tokenHolder address of a token holder which may have the operator
     * address as an operator.
     */
    function isOperatorFor(
        address operator,
        address tokenHolder
    ) public view returns (bool) {
        return operator == tokenHolder ||
            (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
            _operators[tokenHolder][operator];
    }

    /**
     * @dev Function to check the amount of tokens that an owner allowed to a spender.
     * Required for ERC20 compatibility.
     * @param owner address The address which owns the funds.
     * @param spender address The address which will spend the funds.
     * @return A uint256 specifying the amount of tokens still available for the spender.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev Mint tokens. Does not check authorization of operator
     * @dev the caller may ckeck that operator is authorized before calling
     * @param operator address operator requesting the operation
     * @param to address token recipient address
     * @param amount uint256 amount of tokens to mint
     * @param userData bytes extra information defined by the token recipient (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _mint(
        address operator,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
    internal
    {
        require(to != address(0), "ERC777: mint to the zero address");

        // Update state variables
        _totalSupply = _totalSupply.add(amount);
        _balances[to] = _balances[to].add(amount);

        _callTokensReceived(operator, address(0), to, amount, userData, operatorData, true);

        emit Minted(operator, to, amount, userData, operatorData);
        emit Transfer(address(0), to, amount);
    }

    function _transfer(address operator, address from, address to, uint256 amount) private {
        _sendAllowingNoReceptionAck(operator, from, to, amount, "", "");
    }

    function _sendRequiringReceptionAck(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) private {
        _send(operator, from, to, amount, userData, operatorData, true);
    }

    function _sendAllowingNoReceptionAck(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    ) private {
        _send(operator, from, to, amount, userData, operatorData, false);
    }

    /**
     * @dev Send tokens
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _send(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
    private
    {
        require(from != address(0), "ERC777: transfer from the zero address");
        require(to != address(0), "ERC777: transfer to the zero address");

        _callTokensToSend(operator, from, to, amount, userData, operatorData);

        // Update state variables
        _balances[from] = _balances[from].sub(amount);
        _balances[to] = _balances[to].add(amount);

        _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);

        emit Sent(operator, from, to, amount, userData, operatorData);
        emit Transfer(from, to, amount);
    }

    /**
     * @dev Burn tokens
     * @param operator address operator requesting the operation
     * @param from address token holder address
     * @param amount uint256 amount of tokens to burn
     * @param data bytes extra information provided by the token holder
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _burn(
        address operator,
        address from,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    )
    private
    {
        require(from != address(0), "ERC777: burn from the zero address");

        _callTokensToSend(operator, from, address(0), amount, data, operatorData);

        // Update state variables
        _totalSupply = _totalSupply.sub(amount);
        _balances[from] = _balances[from].sub(amount);

        emit Burned(operator, from, amount, data, operatorData);
        emit Transfer(from, address(0), amount);
    }

    function _approve(address owner, address spender, uint256 value) private {
        // TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is
        // currently unnecessary.
        //require(owner != address(0), "ERC777: approve from the zero address");
        require(spender != address(0), "ERC777: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Call from.tokensToSend() if the interface is registered
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _callTokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
    private
    {
        address implementer = _erc1820.getInterfaceImplementer(from, TOKENS_SENDER_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
        }
    }

    /**
     * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
     * tokensReceived() was not registered for the recipient
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _callTokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
    private
    {
        address implementer = _erc1820.getInterfaceImplementer(to, TOKENS_RECIPIENT_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
        } else if (requireReceptionAck) {
            require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
        }
    }
}


Remove redundant require statements (#1409)

* Remove redundant require statements

Now that SafeMath uses require, the require statements are redundant. They were also previously inconsistent because they were only included in some functions, but not others

* Update ERC20.sol

pragma solidity ^0.4.24;

import "./IERC20.sol";
import "../../math/SafeMath.sol";

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
 * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract ERC20 is IERC20 {
  using SafeMath for uint256;

  mapping (address => uint256) private _balances;

  mapping (address => mapping (address => uint256)) private _allowed;

  uint256 private _totalSupply;

  /**
  * @dev Total number of tokens in existence
  */
  function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

  /**
  * @dev Gets the balance of the specified address.
  * @param owner The address to query the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  function balanceOf(address owner) public view returns (uint256) {
    return _balances[owner];
  }

  /**
   * @dev Function to check the amount of tokens that an owner allowed to a spender.
   * @param owner address The address which owns the funds.
   * @param spender address The address which will spend the funds.
   * @return A uint256 specifying the amount of tokens still available for the spender.
   */
  function allowance(
    address owner,
    address spender
   )
    public
    view
    returns (uint256)
  {
    return _allowed[owner][spender];
  }

  /**
  * @dev Transfer token for a specified address
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function transfer(address to, uint256 value) public returns (bool) {
    _transfer(msg.sender, to, value);
    return true;
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   * Beware that changing an allowance with this method brings the risk that someone may use both the old
   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   * @param spender The address which will spend the funds.
   * @param value The amount of tokens to be spent.
   */
  function approve(address spender, uint256 value) public returns (bool) {
    require(spender != address(0));

    _allowed[msg.sender][spender] = value;
    emit Approval(msg.sender, spender, value);
    return true;
  }

  /**
   * @dev Transfer tokens from one address to another
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 the amount of tokens to be transferred
   */
  function transferFrom(
    address from,
    address to,
    uint256 value
  )
    public
    returns (bool)
  {
    _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
    _transfer(from, to, value);
    return true;
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To increment
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param addedValue The amount of tokens to increase the allowance by.
   */
  function increaseAllowance(
    address spender,
    uint256 addedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].add(addedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To decrement
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseAllowance(
    address spender,
    uint256 subtractedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].sub(subtractedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
  * @dev Transfer token for a specified addresses
  * @param from The address to transfer from.
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function _transfer(address from, address to, uint256 value) internal {
    require(to != address(0));

    _balances[from] = _balances[from].sub(value);
    _balances[to] = _balances[to].add(value);
    emit Transfer(from, to, value);
  }

  /**
   * @dev Internal function that mints an amount of the token and assigns it to
   * an account. This encapsulates the modification of balances such that the
   * proper events are emitted.
   * @param account The account that will receive the created tokens.
   * @param value The amount that will be created.
   */
  function _mint(address account, uint256 value) internal {
    require(account != address(0));

    _totalSupply = _totalSupply.add(value);
    _balances[account] = _balances[account].add(value);
    emit Transfer(address(0), account, value);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account.
   * @param account The account whose tokens will be burnt.
   * @param value The amount that will be burnt.
   */
  function _burn(address account, uint256 value) internal {
    require(account != address(0));

    _totalSupply = _totalSupply.sub(value);
    _balances[account] = _balances[account].sub(value);
    emit Transfer(account, address(0), value);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account, deducting from the sender's allowance for said account. Uses the
   * internal burn function.
   * @param account The account whose tokens will be burnt.
   * @param value The amount that will be burnt.
   */
  function _burnFrom(address account, uint256 value) internal {
    require(value <= _allowed[account][msg.sender]);

    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
    // this function needs to emit an event with the updated approval.
    _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(
      value);
    _burn(account, value);
  }
}

pragma solidity ^0.4.24;

import "./IERC20.sol";
import "../../math/SafeMath.sol";

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
 * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract ERC20 is IERC20 {
  using SafeMath for uint256;

  mapping (address => uint256) private _balances;

  mapping (address => mapping (address => uint256)) private _allowed;

  uint256 private _totalSupply;

  /**
  * @dev Total number of tokens in existence
  */
  function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

  /**
  * @dev Gets the balance of the specified address.
  * @param owner The address to query the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  function balanceOf(address owner) public view returns (uint256) {
    return _balances[owner];
  }

  /**
   * @dev Function to check the amount of tokens that an owner allowed to a spender.
   * @param owner address The address which owns the funds.
   * @param spender address The address which will spend the funds.
   * @return A uint256 specifying the amount of tokens still available for the spender.
   */
  function allowance(
    address owner,
    address spender
   )
    public
    view
    returns (uint256)
  {
    return _allowed[owner][spender];
  }

  /**
  * @dev Transfer token for a specified address
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function transfer(address to, uint256 value) public returns (bool) {
    _transfer(msg.sender, to, value);
    return true;
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   * Beware that changing an allowance with this method brings the risk that someone may use both the old
   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   * @param spender The address which will spend the funds.
   * @param value The amount of tokens to be spent.
   */
  function approve(address spender, uint256 value) public returns (bool) {
    require(spender != address(0));

    _allowed[msg.sender][spender] = value;
    emit Approval(msg.sender, spender, value);
    return true;
  }

  /**
   * @dev Transfer tokens from one address to another
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 the amount of tokens to be transferred
   */
  function transferFrom(
    address from,
    address to,
    uint256 value
  )
    public
    returns (bool)
  {
    require(value <= _allowed[from][msg.sender]);

    _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
    _transfer(from, to, value);
    return true;
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To increment
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param addedValue The amount of tokens to increase the allowance by.
   */
  function increaseAllowance(
    address spender,
    uint256 addedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].add(addedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   * approve should be called when allowed_[_spender] == 0. To decrement
   * allowed value is better to use this function to avoid 2 calls (and wait until
   * the first transaction is mined)
   * From MonolithDAO Token.sol
   * @param spender The address which will spend the funds.
   * @param subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseAllowance(
    address spender,
    uint256 subtractedValue
  )
    public
    returns (bool)
  {
    require(spender != address(0));

    _allowed[msg.sender][spender] = (
      _allowed[msg.sender][spender].sub(subtractedValue));
    emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
    return true;
  }

  /**
  * @dev Transfer token for a specified addresses
  * @param from The address to transfer from.
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function _transfer(address from, address to, uint256 value) internal {
    require(value <= _balances[from]);
    require(to != address(0));

    _balances[from] = _balances[from].sub(value);
    _balances[to] = _balances[to].add(value);
    emit Transfer(from, to, value);
  }

  /**
   * @dev Internal function that mints an amount of the token and assigns it to
   * an account. This encapsulates the modification of balances such that the
   * proper events are emitted.
   * @param account The account that will receive the created tokens.
   * @param value The amount that will be created.
   */
  function _mint(address account, uint256 value) internal {
    require(account != address(0));
    _totalSupply = _totalSupply.add(value);
    _balances[account] = _balances[account].add(value);
    emit Transfer(address(0), account, value);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account.
   * @param account The account whose tokens will be burnt.
   * @param value The amount that will be burnt.
   */
  function _burn(address account, uint256 value) internal {
    require(account != address(0));
    require(value <= _balances[account]);

    _totalSupply = _totalSupply.sub(value);
    _balances[account] = _balances[account].sub(value);
    emit Transfer(account, address(0), value);
  }

  /**
   * @dev Internal function that burns an amount of the token of a given
   * account, deducting from the sender's allowance for said account. Uses the
   * internal burn function.
   * @param account The account whose tokens will be burnt.
   * @param value The amount that will be burnt.
   */
  function _burnFrom(address account, uint256 value) internal {
    require(value <= _allowed[account][msg.sender]);

    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
    // this function needs to emit an event with the updated approval.
    _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(
      value);
    _burn(account, value);
  }
}


Add recommendation to initialize all contracts that use Initializable

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be used in certain kinds of exploits since it may allow an attacker to take control of
 * the contract. This includes the implementation contract behind a proxy. You can either invoke the initializer
 * manually, independently of initialization of the proxy, or you can include a constructor to automatically mark it as
 * initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}