ETH Price: $2,494.95 (-0.01%)

Transaction Decoder

Block:
11047258 at Oct-13-2020 12:19:39 PM +UTC
Transaction Fee:
0.001803404 ETH $4.50
Gas Used:
47,458 Gas / 38 Gwei

Emitted Events:

125 NORIDelegator.Approval( owner=[Sender] 0xb086755a5b0b10bd53956936588555f586f5f49d, spender=0x7a250d56...659F2488D, amount=115792089237316195423570985008687907853269984665640564039457584007913129639935 )

Account State Difference:

  Address   Before After State Difference Code
(Spark Pool)
63.066514354593827904 Eth63.068317758593827904 Eth0.001803404
0x79aDD5ef...1E0229BfC
0xB086755a...586f5f49d
1.178445822530645994 Eth
Nonce: 427
1.176642418530645994 Eth
Nonce: 428
0.001803404

Execution Trace

NORIDelegator.approve( spender=0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, amount=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
  • NORIDelegate.approve( spender=0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, value=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
    File 1 of 2: NORIDelegator
    pragma solidity 0.5.17;
    
    pragma experimental ABIEncoderV2;
    
    /**
     * @dev Wrappers over Solidity's arithmetic operations with added overflow
     * checks.
     *
     * Arithmetic operations in Solidity wrap on overflow. This can easily result
     * in bugs, because programmers usually assume that an overflow raises an
     * error, which is the standard behavior in high level programming languages.
     * `SafeMath` restores this intuition by reverting the transaction when an
     * operation overflows.
     *
     * Using this library instead of the unchecked operations eliminates an entire
     * class of bugs, so it's recommended to use it always.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         *
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         *
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            return sub(a, b, "SafeMath: subtraction overflow");
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         *
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b <= a, errorMessage);
            uint256 c = a - b;
    
            return c;
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         *
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) {
                return 0;
            }
    
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            return div(a, b, "SafeMath: division by zero");
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b > 0, errorMessage);
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
            return c;
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return mod(a, b, "SafeMath: modulo by zero");
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts with custom message when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    
    // Storage for a NORI token
    contract NORITokenStorage {
    
        using SafeMath for uint256;
    
        /**
         * @dev Guard variable for re-entrancy checks. Not currently used
         */
        bool internal _notEntered;
    
        /**
         * @notice EIP-20 token name for this token
         */
        string public name;
    
        /**
         * @notice EIP-20 token symbol for this token
         */
        string public symbol;
    
        /**
         * @notice EIP-20 token decimals for this token
         */
        uint8 public decimals;
    
        /**
         * @notice Governor for this contract
         */
        address public gov;
    
        /**
         * @notice Pending governance for this contract
         */
        address public pendingGov;
    
        /**
         * @notice Approved rebaser for this contract
         */
        address public rebaser;
    
        /**
         * @notice Reserve address of NORI protocol
         */
        address public incentivizer;
    
        /**
         * @notice Total supply of NORIs
         */
        uint256 public totalSupply;
    
        /**
         * @notice Internal decimals used to handle scaling factor
         */
        uint256 public constant internalDecimals = 10**24;
    
        /**
         * @notice Used for percentage maths
         */
        uint256 public constant BASE = 10**18;
    
        /**
         * @notice Scaling factor that adjusts everyone's balances
         */
        uint256 public norisScalingFactor;
    
        mapping (address => uint256) internal _noriBalances;
    
        mapping (address => mapping (address => uint256)) internal _allowedFragments;
    
        uint256 public initSupply;
    
    }
    
    contract NORIGovernanceStorage {
        /// @notice A record of each accounts delegate
        mapping (address => address) internal _delegates;
    
        /// @notice A checkpoint for marking number of votes from a given block
        struct Checkpoint {
            uint32 fromBlock;
            uint256 votes;
        }
    
        /// @notice A record of votes checkpoints for each account, by index
        mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
    
        /// @notice The number of checkpoints for each account
        mapping (address => uint32) public numCheckpoints;
    
        /// @notice The EIP-712 typehash for the contract's domain
        bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
    
        /// @notice The EIP-712 typehash for the delegation struct used by the contract
        bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
    
        /// @notice A record of states for signing / validating signatures
        mapping (address => uint) public nonces;
    }
    
    contract NORITokenInterface is NORITokenStorage, NORIGovernanceStorage {
    
        /// @notice An event thats emitted when an account changes its delegate
        event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
    
        /// @notice An event thats emitted when a delegate account's vote balance changes
        event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
    
        /**
         * @notice Event emitted when tokens are rebased
         */
        event Rebase(uint256 epoch, uint256 prevNorisScalingFactor, uint256 newNorisScalingFactor);
    
        /*** Gov Events ***/
    
        /**
         * @notice Event emitted when pendingGov is changed
         */
        event NewPendingGov(address oldPendingGov, address newPendingGov);
    
        /**
         * @notice Event emitted when gov is changed
         */
        event NewGov(address oldGov, address newGov);
    
        /**
         * @notice Sets the rebaser contract
         */
        event NewRebaser(address oldRebaser, address newRebaser);
    
        /**
         * @notice Sets the incentivizer contract
         */
        event NewIncentivizer(address oldIncentivizer, address newIncentivizer);
    
        /* - ERC20 Events - */
    
        /**
         * @notice EIP20 Transfer event
         */
        event Transfer(address indexed from, address indexed to, uint amount);
    
        /**
         * @notice EIP20 Approval event
         */
        event Approval(address indexed owner, address indexed spender, uint amount);
    
        /* - Extra Events - */
        /**
         * @notice Tokens minted event
         */
        event Mint(address to, uint256 amount);
    
        // Public functions
        function transfer(address to, uint256 value) external returns(bool);
        function transferFrom(address from, address to, uint256 value) external returns(bool);
        function balanceOf(address who) external view returns(uint256);
        function balanceOfUnderlying(address who) external view returns(uint256);
        function allowance(address owner_, address spender) external view returns(uint256);
        function approve(address spender, uint256 value) external returns (bool);
        function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
        function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
        function maxScalingFactor() external view returns (uint256);
    
        /* - Governance Functions - */
        function getPriorVotes(address account, uint blockNumber) external view returns (uint256);
        function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external;
        function delegate(address delegatee) external;
        function delegates(address delegator) external view returns (address);
        function getCurrentVotes(address account) external view returns (uint256);
    
        /* - Permissioned/Governance functions - */
        function mint(address to, uint256 amount) external returns (bool);
        function rebase(uint256 epoch, uint256 indexDelta, bool positive) external returns (uint256);
        function _setRebaser(address rebaser_) external;
        function _setIncentivizer(address incentivizer_) external;
        function _setPendingGov(address pendingGov_) external;
        function _acceptGov() external;
    }
    
    
    contract NORIGovernanceToken is NORITokenInterface {
    
          /// @notice An event thats emitted when an account changes its delegate
        event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
    
        /// @notice An event thats emitted when a delegate account's vote balance changes
        event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
    
        /**
         * @notice Delegate votes from `msg.sender` to `delegatee`
         * @param delegator The address to get delegatee for
         */
        function delegates(address delegator)
            external
            view
            returns (address)
        {
            return _delegates[delegator];
        }
    
       /**
        * @notice Delegate votes from `msg.sender` to `delegatee`
        * @param delegatee The address to delegate votes to
        */
        function delegate(address delegatee) external {
            return _delegate(msg.sender, delegatee);
        }
    
        /**
         * @notice Delegates votes from signatory to `delegatee`
         * @param delegatee The address to delegate votes to
         * @param nonce The contract state required to match the signature
         * @param expiry The time at which to expire the signature
         * @param v The recovery byte of the signature
         * @param r Half of the ECDSA signature pair
         * @param s Half of the ECDSA signature pair
         */
        function delegateBySig(
            address delegatee,
            uint nonce,
            uint expiry,
            uint8 v,
            bytes32 r,
            bytes32 s
        )
            external
        {
            bytes32 domainSeparator = keccak256(
                abi.encode(
                    DOMAIN_TYPEHASH,
                    keccak256(bytes(name)),
                    getChainId(),
                    address(this)
                )
            );
    
            bytes32 structHash = keccak256(
                abi.encode(
                    DELEGATION_TYPEHASH,
                    delegatee,
                    nonce,
                    expiry
                )
            );
    
            bytes32 digest = keccak256(
                abi.encodePacked(
                    "\x19\x01",
                    domainSeparator,
                    structHash
                )
            );
    
            address signatory = ecrecover(digest, v, r, s);
            require(signatory != address(0), "NORI::delegateBySig: invalid signature");
            require(nonce == nonces[signatory]++, "NORI::delegateBySig: invalid nonce");
            require(now <= expiry, "NORI::delegateBySig: signature expired");
            return _delegate(signatory, delegatee);
        }
    
        /**
         * @notice Gets the current votes balance for `account`
         * @param account The address to get votes balance
         * @return The number of current votes for `account`
         */
        function getCurrentVotes(address account)
            external
            view
            returns (uint256)
        {
            uint32 nCheckpoints = numCheckpoints[account];
            return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
        }
    
        /**
         * @notice Determine the prior number of votes for an account as of a block number
         * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
         * @param account The address of the account to check
         * @param blockNumber The block number to get the vote balance at
         * @return The number of votes the account had as of the given block
         */
        function getPriorVotes(address account, uint blockNumber)
            external
            view
            returns (uint256)
        {
            require(blockNumber < block.number, "NORI::getPriorVotes: not yet determined");
    
            uint32 nCheckpoints = numCheckpoints[account];
            if (nCheckpoints == 0) {
                return 0;
            }
    
            // First check most recent balance
            if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
                return checkpoints[account][nCheckpoints - 1].votes;
            }
    
            // Next check implicit zero balance
            if (checkpoints[account][0].fromBlock > blockNumber) {
                return 0;
            }
    
            uint32 lower = 0;
            uint32 upper = nCheckpoints - 1;
            while (upper > lower) {
                uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
                Checkpoint memory cp = checkpoints[account][center];
                if (cp.fromBlock == blockNumber) {
                    return cp.votes;
                } else if (cp.fromBlock < blockNumber) {
                    lower = center;
                } else {
                    upper = center - 1;
                }
            }
            return checkpoints[account][lower].votes;
        }
    
        function _delegate(address delegator, address delegatee)
            internal
        {
            address currentDelegate = _delegates[delegator];
            uint256 delegatorBalance = _noriBalances[delegator]; // balance of underlying NORIs (not scaled);
            _delegates[delegator] = delegatee;
    
            emit DelegateChanged(delegator, currentDelegate, delegatee);
    
            _moveDelegates(currentDelegate, delegatee, delegatorBalance);
        }
    
        function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
            if (srcRep != dstRep && amount > 0) {
                if (srcRep != address(0)) {
                    // decrease old representative
                    uint32 srcRepNum = numCheckpoints[srcRep];
                    uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                    uint256 srcRepNew = srcRepOld.sub(amount);
                    _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
                }
    
                if (dstRep != address(0)) {
                    // increase new representative
                    uint32 dstRepNum = numCheckpoints[dstRep];
                    uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                    uint256 dstRepNew = dstRepOld.add(amount);
                    _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
                }
            }
        }
    
        function _writeCheckpoint(
            address delegatee,
            uint32 nCheckpoints,
            uint256 oldVotes,
            uint256 newVotes
        )
            internal
        {
            uint32 blockNumber = safe32(block.number, "NORI::_writeCheckpoint: block number exceeds 32 bits");
    
            if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
                checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
            } else {
                checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
                numCheckpoints[delegatee] = nCheckpoints + 1;
            }
    
            emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
        }
    
        function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
            require(n < 2**32, errorMessage);
            return uint32(n);
        }
    
        function getChainId() internal pure returns (uint) {
            uint256 chainId;
            assembly { chainId := chainid() }
            return chainId;
        }
    }
    
    contract NORIToken is NORIGovernanceToken {
        // Modifiers
        modifier onlyGov() {
            require(msg.sender == gov);
            _;
        }
    
        modifier onlyRebaser() {
            require(msg.sender == rebaser);
            _;
        }
    
        modifier onlyMinter() {
            require(msg.sender == rebaser || msg.sender == incentivizer || msg.sender == gov, "not minter");
            _;
        }
    
        modifier validRecipient(address to) {
            require(to != address(0x0));
            require(to != address(this));
            _;
        }
    
        function initialize(
            string memory name_,
            string memory symbol_,
            uint8 decimals_
        )
            public
        {
            require(norisScalingFactor == 0, "already initialized");
            name = name_;
            symbol = symbol_;
            decimals = decimals_;
        }
    
    
        /**
        * @notice Computes the current max scaling factor
        */
        function maxScalingFactor()
            external
            view
            returns (uint256)
        {
            return _maxScalingFactor();
        }
    
        function _maxScalingFactor()
            internal
            view
            returns (uint256)
        {
            // scaling factor can only go up to 2**256-1 = initSupply * norisScalingFactor
            // this is used to check if norisScalingFactor will be too high to compute balances when rebasing.
            return uint256(-1) / initSupply;
        }
    
        /**
        * @notice Mints new tokens, increasing totalSupply, initSupply, and a users balance.
        * @dev Limited to onlyMinter modifier
        */
        function mint(address to, uint256 amount)
            external
            onlyMinter
            returns (bool)
        {
            _mint(to, amount);
            return true;
        }
    
        function _mint(address to, uint256 amount)
            internal
        {
          // increase totalSupply
          totalSupply = totalSupply.add(amount);
    
          // get underlying value
          uint256 noriValue = amount.mul(internalDecimals).div(norisScalingFactor);
    
          // increase initSupply
          initSupply = initSupply.add(noriValue);
    
          // make sure the mint didnt push maxScalingFactor too low
          require(norisScalingFactor <= _maxScalingFactor(), "max scaling factor too low");
    
          // add balance
          _noriBalances[to] = _noriBalances[to].add(noriValue);
    
          // add delegates to the minter
          _moveDelegates(address(0), _delegates[to], noriValue);
          emit Mint(to, amount);
        }
    
        /* - ERC20 functionality - */
    
        /**
        * @dev Transfer tokens to a specified address.
        * @param to The address to transfer to.
        * @param value The amount to be transferred.
        * @return True on success, false otherwise.
        */
        function transfer(address to, uint256 value)
            external
            validRecipient(to)
            returns (bool)
        {
            // underlying balance is stored in noris, so divide by current scaling factor
    
            // note, this means as scaling factor grows, dust will be untransferrable.
            // minimum transfer value == norisScalingFactor / 1e24;
    
            // get amount in underlying
            uint256 noriValue = value.mul(internalDecimals).div(norisScalingFactor);
    
            // sub from balance of sender
            _noriBalances[msg.sender] = _noriBalances[msg.sender].sub(noriValue);
    
            // add to balance of receiver
            _noriBalances[to] = _noriBalances[to].add(noriValue);
            emit Transfer(msg.sender, to, value);
    
            _moveDelegates(_delegates[msg.sender], _delegates[to], noriValue);
            return true;
        }
    
        /**
        * @dev Transfer tokens from one address to another.
        * @param from The address you want to send tokens from.
        * @param to The address you want to transfer to.
        * @param value The amount of tokens to be transferred.
        */
        function transferFrom(address from, address to, uint256 value)
            external
            validRecipient(to)
            returns (bool)
        {
            // decrease allowance
            _allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender].sub(value);
    
            // get value in noris
            uint256 noriValue = value.mul(internalDecimals).div(norisScalingFactor);
    
            // sub from from
            _noriBalances[from] = _noriBalances[from].sub(noriValue);
            _noriBalances[to] = _noriBalances[to].add(noriValue);
            emit Transfer(from, to, value);
    
            _moveDelegates(_delegates[from], _delegates[to], noriValue);
            return true;
        }
    
        /**
        * @param who The address to query.
        * @return The balance of the specified address.
        */
        function balanceOf(address who)
          external
          view
          returns (uint256)
        {
          return _noriBalances[who].mul(norisScalingFactor).div(internalDecimals);
        }
    
        /** @notice Currently returns the internal storage amount
        * @param who The address to query.
        * @return The underlying balance of the specified address.
        */
        function balanceOfUnderlying(address who)
          external
          view
          returns (uint256)
        {
          return _noriBalances[who];
        }
    
        /**
         * @dev Function to check the amount of tokens that an owner has allowed to a spender.
         * @param owner_ The address which owns the funds.
         * @param spender The address which will spend the funds.
         * @return The number of tokens still available for the spender.
         */
        function allowance(address owner_, address spender)
            external
            view
            returns (uint256)
        {
            return _allowedFragments[owner_][spender];
        }
    
        /**
         * @dev Approve the passed address to spend the specified amount of tokens on behalf of
         * msg.sender. This method is included for ERC20 compatibility.
         * increaseAllowance and decreaseAllowance should be used instead.
         * Changing an allowance with this method brings the risk that someone may transfer both
         * the old and the new allowance - if they are both greater than zero - if a transfer
         * transaction is mined before the later approve() call is mined.
         *
         * @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)
        {
            _allowedFragments[msg.sender][spender] = value;
            emit Approval(msg.sender, spender, value);
            return true;
        }
    
        /**
         * @dev Increase the amount of tokens that an owner has allowed to a spender.
         * This method should be used instead of approve() to avoid the double approval vulnerability
         * described above.
         * @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)
            external
            returns (bool)
        {
            _allowedFragments[msg.sender][spender] =
                _allowedFragments[msg.sender][spender].add(addedValue);
            emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
            return true;
        }
    
        /**
         * @dev Decrease the amount of tokens that an owner has allowed to a spender.
         *
         * @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)
            external
            returns (bool)
        {
            uint256 oldValue = _allowedFragments[msg.sender][spender];
            if (subtractedValue >= oldValue) {
                _allowedFragments[msg.sender][spender] = 0;
            } else {
                _allowedFragments[msg.sender][spender] = oldValue.sub(subtractedValue);
            }
            emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
            return true;
        }
    
        /* - Governance Functions - */
    
        /** @notice sets the rebaser
         * @param rebaser_ The address of the rebaser contract to use for authentication.
         */
        function _setRebaser(address rebaser_)
            external
            onlyGov
        {
            address oldRebaser = rebaser;
            rebaser = rebaser_;
            emit NewRebaser(oldRebaser, rebaser_);
        }
    
        /** @notice sets the incentivizer
         * @param incentivizer_ The address of the rebaser contract to use for authentication.
         */
        function _setIncentivizer(address incentivizer_)
            external
            onlyGov
        {
            address oldIncentivizer = incentivizer;
            incentivizer = incentivizer_;
            emit NewIncentivizer(oldIncentivizer, incentivizer_);
        }
    
        /** @notice sets the pendingGov
         * @param pendingGov_ The address of the rebaser contract to use for authentication.
         */
        function _setPendingGov(address pendingGov_)
            external
            onlyGov
        {
            address oldPendingGov = pendingGov;
            pendingGov = pendingGov_;
            emit NewPendingGov(oldPendingGov, pendingGov_);
        }
    
        /** @notice lets msg.sender accept governance
         *
         */
        function _acceptGov()
            external
        {
            require(msg.sender == pendingGov, "!pending");
            address oldGov = gov;
            gov = pendingGov;
            pendingGov = address(0);
            emit NewGov(oldGov, gov);
        }
    
        /* - Extras - */
    
        /**
        * @notice Initiates a new rebase operation, provided the minimum time period has elapsed.
        *
        * @dev The supply adjustment equals (totalSupply * DeviationFromTargetRate) / rebaseLag
        *      Where DeviationFromTargetRate is (MarketOracleRate - targetRate) / targetRate
        *      and targetRate is CpiOracleRate / baseCpi
        */
        function rebase(
            uint256 epoch,
            uint256 indexDelta,
            bool positive
        )
            external
            onlyRebaser
            returns (uint256)
        {
            if (indexDelta == 0) {
              emit Rebase(epoch, norisScalingFactor, norisScalingFactor);
              return totalSupply;
            }
    
            uint256 prevNorisScalingFactor = norisScalingFactor;
    
            if (!positive) {
               norisScalingFactor = norisScalingFactor.mul(BASE.sub(indexDelta)).div(BASE);
            } else {
                uint256 newScalingFactor = norisScalingFactor.mul(BASE.add(indexDelta)).div(BASE);
                if (newScalingFactor < _maxScalingFactor()) {
                    norisScalingFactor = newScalingFactor;
                } else {
                  norisScalingFactor = _maxScalingFactor();
                }
            }
    
            totalSupply = initSupply.mul(norisScalingFactor);
            emit Rebase(epoch, prevNorisScalingFactor, norisScalingFactor);
            return totalSupply;
        }
    }
    
    contract NORI is NORIToken {
        /**
         * @notice Initialize the new money market
         * @param name_ ERC-20 name of this token
         * @param symbol_ ERC-20 symbol of this token
         * @param decimals_ ERC-20 decimal precision of this token
         */
        function initialize(
            string memory name_,
            string memory symbol_,
            uint8 decimals_,
            address initial_owner,
            uint256 initSupply_
        )
            public
        {
            require(initSupply_ > 0, "0 init supply");
    
            super.initialize(name_, symbol_, decimals_);
    
            initSupply = initSupply_.mul(10**24/ (BASE));
            totalSupply = initSupply_;
            norisScalingFactor = BASE;
            _noriBalances[initial_owner] = initSupply_.mul(10**24 / (BASE));
    
            // owner renounces ownership after deployment as they need to set
            // rebaser and incentivizer
            // gov = gov_;
        }
    }
    
    
    contract NORIDelegationStorage {
        /**
         * @notice Implementation address for this contract
         */
        address public implementation;
    }
    
    contract NORIDelegatorInterface is NORIDelegationStorage {
        /**
         * @notice Emitted when implementation is changed
         */
        event NewImplementation(address oldImplementation, address newImplementation);
    
        /**
         * @notice Called by the gov to update the implementation of the delegator
         * @param implementation_ The address of the new implementation for delegation
         * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
         * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
         */
        function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;
    }
    
    contract NORIDelegateInterface is NORIDelegationStorage {
        /**
         * @notice Called by the delegator on a delegate to initialize it for duty
         * @dev Should revert if any issues arise which make it unfit for delegation
         * @param data The encoded bytes data for any initialization
         */
        function _becomeImplementation(bytes memory data) public;
    
        /**
         * @notice Called by the delegator on a delegate to forfeit its responsibility
         */
        function _resignImplementation() public;
    }
    
    
    contract NORIDelegate is NORI, NORIDelegateInterface {
        /**
         * @notice Construct an empty delegate
         */
        constructor() public {}
    
        /**
         * @notice Called by the delegator on a delegate to initialize it for duty
         * @param data The encoded bytes data for any initialization
         */
        function _becomeImplementation(bytes memory data) public {
            // Shh -- currently unused
            data;
    
            // Shh -- we don't ever want this hook to be marked pure
            if (false) {
                implementation = address(0);
            }
    
            require(msg.sender == gov, "only the gov may call _becomeImplementation");
        }
    
        /**
         * @notice Called by the delegator on a delegate to forfeit its responsibility
         */
        function _resignImplementation() public {
            // Shh -- we don't ever want this hook to be marked pure
            if (false) {
                implementation = address(0);
            }
    
            require(msg.sender == gov, "only the gov may call _resignImplementation");
        }
    }
    
    contract NORIDelegator is NORITokenInterface, NORIDelegatorInterface {
        /**
         * @notice Construct a new NORI
         * @param name_ ERC-20 name of this token
         * @param symbol_ ERC-20 symbol of this token
         * @param decimals_ ERC-20 decimal precision of this token
         * @param initSupply_ Initial token amount
         * @param implementation_ The address of the implementation the contract delegates to
         * @param becomeImplementationData The encoded args for becomeImplementation
         */
        constructor(
            string memory name_,
            string memory symbol_,
            uint8 decimals_,
            uint256 initSupply_,
            address implementation_,
            bytes memory becomeImplementationData
        )
            public
        {
    
    
            // Creator of the contract is gov during initialization
            gov = msg.sender;
    
            // First delegate gets to initialize the delegator (i.e. storage contract)
            delegateTo(
                implementation_,
                abi.encodeWithSignature(
                    "initialize(string,string,uint8,address,uint256)",
                    name_,
                    symbol_,
                    decimals_,
                    msg.sender,
                    initSupply_
                )
            );
    
            // New implementations always get set via the settor (post-initialize)
            _setImplementation(implementation_, false, becomeImplementationData);
    
        }
    
        /**
         * @notice Called by the gov to update the implementation of the delegator
         * @param implementation_ The address of the new implementation for delegation
         * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
         * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
         */
        function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public {
            require(msg.sender == gov, "NORIDelegator::_setImplementation: Caller must be gov");
    
            if (allowResign) {
                delegateToImplementation(abi.encodeWithSignature("_resignImplementation()"));
            }
    
            address oldImplementation = implementation;
            implementation = implementation_;
    
            delegateToImplementation(abi.encodeWithSignature("_becomeImplementation(bytes)", becomeImplementationData));
    
            emit NewImplementation(oldImplementation, implementation);
        }
    
        /**
         * @notice Sender supplies assets into the market and receives cTokens in exchange
         * @dev Accrues interest whether or not the operation succeeds, unless reverted
         * @param mintAmount The amount of the underlying asset to supply
         * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
         */
        function mint(address to, uint256 mintAmount)
            external
            returns (bool)
        {
            to; mintAmount; // Shh
            delegateAndReturn();
        }
    
        /**
         * @notice Transfer `amount` tokens from `msg.sender` to `dst`
         * @param dst The address of the destination account
         * @param amount The number of tokens to transfer
         * @return Whether or not the transfer succeeded
         */
        function transfer(address dst, uint256 amount)
            external
            returns (bool)
        {
            dst; amount; // Shh
            delegateAndReturn();
        }
    
        /**
         * @notice Transfer `amount` tokens from `src` to `dst`
         * @param src The address of the source account
         * @param dst The address of the destination account
         * @param amount The number of tokens to transfer
         * @return Whether or not the transfer succeeded
         */
        function transferFrom(
            address src,
            address dst,
            uint256 amount
        )
            external
            returns (bool)
        {
            src; dst; amount; // Shh
            delegateAndReturn();
        }
    
        /**
         * @notice Approve `spender` to transfer up to `amount` from `src`
         * @dev This will overwrite the approval amount for `spender`
         *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
         * @param spender The address of the account which may transfer tokens
         * @param amount The number of tokens that are approved (-1 means infinite)
         * @return Whether or not the approval succeeded
         */
        function approve(
            address spender,
            uint256 amount
        )
            external
            returns (bool)
        {
            spender; amount; // Shh
            delegateAndReturn();
        }
    
        /**
         * @dev Increase the amount of tokens that an owner has allowed to a spender.
         * This method should be used instead of approve() to avoid the double approval vulnerability
         * described above.
         * @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
        )
            external
            returns (bool)
        {
            spender; addedValue; // Shh
            delegateAndReturn();
        }
    
        function maxScalingFactor()
            external
            view
            returns (uint256)
        {
            delegateToViewAndReturn();
        }
    
        function rebase(
            uint256 epoch,
            uint256 indexDelta,
            bool positive
        )
            external
            returns (uint256)
        {
            epoch; indexDelta; positive;
            delegateAndReturn();
        }
    
        /**
         * @dev Decrease the amount of tokens that an owner has allowed to a spender.
         *
         * @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
        )
            external
            returns (bool)
        {
            spender; subtractedValue; // Shh
            delegateAndReturn();
        }
    
        /**
         * @notice Get the current allowance from `owner` for `spender`
         * @param owner The address of the account which owns the tokens to be spent
         * @param spender The address of the account which may transfer tokens
         * @return The number of tokens allowed to be spent (-1 means infinite)
         */
        function allowance(
            address owner,
            address spender
        )
            external
            view
            returns (uint256)
        {
            owner; spender; // Shh
            delegateToViewAndReturn();
        }
    
        /**
         * @notice Get the current allowance from `owner` for `spender`
         * @param delegator The address of the account which has designated a delegate
         * @return Address of delegatee
         */
        function delegates(
            address delegator
        )
            external
            view
            returns (address)
        {
            delegator; // Shh
            delegateToViewAndReturn();
        }
    
        /**
         * @notice Get the token balance of the `owner`
         * @param owner The address of the account to query
         * @return The number of tokens owned by `owner`
         */
        function balanceOf(address owner)
            external
            view
            returns (uint256)
        {
            owner; // Shh
            delegateToViewAndReturn();
        }
    
        /**
         * @notice Currently unused. For future compatability
         * @param owner The address of the account to query
         * @return The number of underlying tokens owned by `owner`
         */
        function balanceOfUnderlying(address owner)
            external
            view
            returns (uint256)
        {
            owner; // Shh
            delegateToViewAndReturn();
        }
    
        /*** Gov Functions ***/
    
        /**
          * @notice Begins transfer of gov rights. The newPendingGov must call `_acceptGov` to finalize the transfer.
          * @dev Gov function to begin change of gov. The newPendingGov must call `_acceptGov` to finalize the transfer.
          * @param newPendingGov New pending gov.
          */
        function _setPendingGov(address newPendingGov)
            external
        {
            newPendingGov; // Shh
            delegateAndReturn();
        }
    
        function _setRebaser(address rebaser_)
            external
        {
            rebaser_; // Shh
            delegateAndReturn();
        }
    
        function _setIncentivizer(address incentivizer_)
            external
        {
            incentivizer_; // Shh
            delegateAndReturn();
        }
    
        /**
          * @notice Accepts transfer of gov rights. msg.sender must be pendingGov
          * @dev Gov function for pending gov to accept role and update gov
          * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
          */
        function _acceptGov()
            external
        {
            delegateAndReturn();
        }
    
    
        function getPriorVotes(address account, uint blockNumber)
            external
            view
            returns (uint256)
        {
            account; blockNumber;
            delegateToViewAndReturn();
        }
    
        function delegateBySig(
            address delegatee,
            uint nonce,
            uint expiry,
            uint8 v,
            bytes32 r,
            bytes32 s
        )
            external
        {
            delegatee; nonce; expiry; v; r; s;
            delegateAndReturn();
        }
    
        function delegate(address delegatee)
            external
        {
            delegatee;
            delegateAndReturn();
        }
    
        function getCurrentVotes(address account)
            external
            view
            returns (uint256)
        {
            account;
            delegateToViewAndReturn();
        }
    
        /**
         * @notice Internal method to delegate execution to another contract
         * @dev It returns to the external caller whatever the implementation returns or forwards reverts
         * @param callee The contract to delegatecall
         * @param data The raw data to delegatecall
         * @return The returned bytes from the delegatecall
         */
        function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {
            (bool success, bytes memory returnData) = callee.delegatecall(data);
            assembly {
                if eq(success, 0) {
                    revert(add(returnData, 0x20), returndatasize)
                }
            }
            return returnData;
        }
    
        /**
         * @notice Delegates execution to the implementation contract
         * @dev It returns to the external caller whatever the implementation returns or forwards reverts
         * @param data The raw data to delegatecall
         * @return The returned bytes from the delegatecall
         */
        function delegateToImplementation(bytes memory data) public returns (bytes memory) {
            return delegateTo(implementation, data);
        }
    
        /**
         * @notice Delegates execution to an implementation contract
         * @dev It returns to the external caller whatever the implementation returns or forwards reverts
         *  There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.
         * @param data The raw data to delegatecall
         * @return The returned bytes from the delegatecall
         */
        function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {
            (bool success, bytes memory returnData) = address(this).staticcall(abi.encodeWithSignature("delegateToImplementation(bytes)", data));
            assembly {
                if eq(success, 0) {
                    revert(add(returnData, 0x20), returndatasize)
                }
            }
            return abi.decode(returnData, (bytes));
        }
    
        function delegateToViewAndReturn() private view returns (bytes memory) {
            (bool success, ) = address(this).staticcall(abi.encodeWithSignature("delegateToImplementation(bytes)", msg.data));
    
            assembly {
                let free_mem_ptr := mload(0x40)
                returndatacopy(free_mem_ptr, 0, returndatasize)
    
                switch success
                case 0 { revert(free_mem_ptr, returndatasize) }
                default { return(add(free_mem_ptr, 0x40), returndatasize) }
            }
        }
    
        function delegateAndReturn() private returns (bytes memory) {
            (bool success, ) = implementation.delegatecall(msg.data);
    
            assembly {
                let free_mem_ptr := mload(0x40)
                returndatacopy(free_mem_ptr, 0, returndatasize)
    
                switch success
                case 0 { revert(free_mem_ptr, returndatasize) }
                default { return(free_mem_ptr, returndatasize) }
            }
        }
    
        /**
         * @notice Delegates execution to an implementation contract
         * @dev It returns to the external caller whatever the implementation returns or forwards reverts
         */
        function () external payable {
            require(msg.value == 0,"NORIDelegator:fallback: cannot send value to fallback");
    
            // delegate all other functions to current implementation
            delegateAndReturn();
        }
    }

    File 2 of 2: NORIDelegate
    pragma solidity 0.5.17;
    
    pragma experimental ABIEncoderV2;
    
    /**
     * @dev Wrappers over Solidity's arithmetic operations with added overflow
     * checks.
     *
     * Arithmetic operations in Solidity wrap on overflow. This can easily result
     * in bugs, because programmers usually assume that an overflow raises an
     * error, which is the standard behavior in high level programming languages.
     * `SafeMath` restores this intuition by reverting the transaction when an
     * operation overflows.
     *
     * Using this library instead of the unchecked operations eliminates an entire
     * class of bugs, so it's recommended to use it always.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         *
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         *
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            return sub(a, b, "SafeMath: subtraction overflow");
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         *
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b <= a, errorMessage);
            uint256 c = a - b;
    
            return c;
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         *
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) {
                return 0;
            }
    
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            return div(a, b, "SafeMath: division by zero");
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b > 0, errorMessage);
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
            return c;
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return mod(a, b, "SafeMath: modulo by zero");
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts with custom message when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    
    // Storage for a NORI token
    contract NORITokenStorage {
    
        using SafeMath for uint256;
    
        /**
         * @dev Guard variable for re-entrancy checks. Not currently used
         */
        bool internal _notEntered;
    
        /**
         * @notice EIP-20 token name for this token
         */
        string public name;
    
        /**
         * @notice EIP-20 token symbol for this token
         */
        string public symbol;
    
        /**
         * @notice EIP-20 token decimals for this token
         */
        uint8 public decimals;
    
        /**
         * @notice Governor for this contract
         */
        address public gov;
    
        /**
         * @notice Pending governance for this contract
         */
        address public pendingGov;
    
        /**
         * @notice Approved rebaser for this contract
         */
        address public rebaser;
    
        /**
         * @notice Reserve address of NORI protocol
         */
        address public incentivizer;
    
        /**
         * @notice Total supply of NORIs
         */
        uint256 public totalSupply;
    
        /**
         * @notice Internal decimals used to handle scaling factor
         */
        uint256 public constant internalDecimals = 10**24;
    
        /**
         * @notice Used for percentage maths
         */
        uint256 public constant BASE = 10**18;
    
        /**
         * @notice Scaling factor that adjusts everyone's balances
         */
        uint256 public norisScalingFactor;
    
        mapping (address => uint256) internal _noriBalances;
    
        mapping (address => mapping (address => uint256)) internal _allowedFragments;
    
        uint256 public initSupply;
    
    }
    
    contract NORIGovernanceStorage {
        /// @notice A record of each accounts delegate
        mapping (address => address) internal _delegates;
    
        /// @notice A checkpoint for marking number of votes from a given block
        struct Checkpoint {
            uint32 fromBlock;
            uint256 votes;
        }
    
        /// @notice A record of votes checkpoints for each account, by index
        mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
    
        /// @notice The number of checkpoints for each account
        mapping (address => uint32) public numCheckpoints;
    
        /// @notice The EIP-712 typehash for the contract's domain
        bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
    
        /// @notice The EIP-712 typehash for the delegation struct used by the contract
        bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
    
        /// @notice A record of states for signing / validating signatures
        mapping (address => uint) public nonces;
    }
    
    contract NORITokenInterface is NORITokenStorage, NORIGovernanceStorage {
    
        /// @notice An event thats emitted when an account changes its delegate
        event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
    
        /// @notice An event thats emitted when a delegate account's vote balance changes
        event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
    
        /**
         * @notice Event emitted when tokens are rebased
         */
        event Rebase(uint256 epoch, uint256 prevNorisScalingFactor, uint256 newNorisScalingFactor);
    
        /*** Gov Events ***/
    
        /**
         * @notice Event emitted when pendingGov is changed
         */
        event NewPendingGov(address oldPendingGov, address newPendingGov);
    
        /**
         * @notice Event emitted when gov is changed
         */
        event NewGov(address oldGov, address newGov);
    
        /**
         * @notice Sets the rebaser contract
         */
        event NewRebaser(address oldRebaser, address newRebaser);
    
        /**
         * @notice Sets the incentivizer contract
         */
        event NewIncentivizer(address oldIncentivizer, address newIncentivizer);
    
        /* - ERC20 Events - */
    
        /**
         * @notice EIP20 Transfer event
         */
        event Transfer(address indexed from, address indexed to, uint amount);
    
        /**
         * @notice EIP20 Approval event
         */
        event Approval(address indexed owner, address indexed spender, uint amount);
    
        /* - Extra Events - */
        /**
         * @notice Tokens minted event
         */
        event Mint(address to, uint256 amount);
    
        // Public functions
        function transfer(address to, uint256 value) external returns(bool);
        function transferFrom(address from, address to, uint256 value) external returns(bool);
        function balanceOf(address who) external view returns(uint256);
        function balanceOfUnderlying(address who) external view returns(uint256);
        function allowance(address owner_, address spender) external view returns(uint256);
        function approve(address spender, uint256 value) external returns (bool);
        function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
        function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
        function maxScalingFactor() external view returns (uint256);
    
        /* - Governance Functions - */
        function getPriorVotes(address account, uint blockNumber) external view returns (uint256);
        function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external;
        function delegate(address delegatee) external;
        function delegates(address delegator) external view returns (address);
        function getCurrentVotes(address account) external view returns (uint256);
    
        /* - Permissioned/Governance functions - */
        function mint(address to, uint256 amount) external returns (bool);
        function rebase(uint256 epoch, uint256 indexDelta, bool positive) external returns (uint256);
        function _setRebaser(address rebaser_) external;
        function _setIncentivizer(address incentivizer_) external;
        function _setPendingGov(address pendingGov_) external;
        function _acceptGov() external;
    }
    
    
    contract NORIGovernanceToken is NORITokenInterface {
    
          /// @notice An event thats emitted when an account changes its delegate
        event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
    
        /// @notice An event thats emitted when a delegate account's vote balance changes
        event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
    
        /**
         * @notice Delegate votes from `msg.sender` to `delegatee`
         * @param delegator The address to get delegatee for
         */
        function delegates(address delegator)
            external
            view
            returns (address)
        {
            return _delegates[delegator];
        }
    
       /**
        * @notice Delegate votes from `msg.sender` to `delegatee`
        * @param delegatee The address to delegate votes to
        */
        function delegate(address delegatee) external {
            return _delegate(msg.sender, delegatee);
        }
    
        /**
         * @notice Delegates votes from signatory to `delegatee`
         * @param delegatee The address to delegate votes to
         * @param nonce The contract state required to match the signature
         * @param expiry The time at which to expire the signature
         * @param v The recovery byte of the signature
         * @param r Half of the ECDSA signature pair
         * @param s Half of the ECDSA signature pair
         */
        function delegateBySig(
            address delegatee,
            uint nonce,
            uint expiry,
            uint8 v,
            bytes32 r,
            bytes32 s
        )
            external
        {
            bytes32 domainSeparator = keccak256(
                abi.encode(
                    DOMAIN_TYPEHASH,
                    keccak256(bytes(name)),
                    getChainId(),
                    address(this)
                )
            );
    
            bytes32 structHash = keccak256(
                abi.encode(
                    DELEGATION_TYPEHASH,
                    delegatee,
                    nonce,
                    expiry
                )
            );
    
            bytes32 digest = keccak256(
                abi.encodePacked(
                    "\x19\x01",
                    domainSeparator,
                    structHash
                )
            );
    
            address signatory = ecrecover(digest, v, r, s);
            require(signatory != address(0), "NORI::delegateBySig: invalid signature");
            require(nonce == nonces[signatory]++, "NORI::delegateBySig: invalid nonce");
            require(now <= expiry, "NORI::delegateBySig: signature expired");
            return _delegate(signatory, delegatee);
        }
    
        /**
         * @notice Gets the current votes balance for `account`
         * @param account The address to get votes balance
         * @return The number of current votes for `account`
         */
        function getCurrentVotes(address account)
            external
            view
            returns (uint256)
        {
            uint32 nCheckpoints = numCheckpoints[account];
            return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
        }
    
        /**
         * @notice Determine the prior number of votes for an account as of a block number
         * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
         * @param account The address of the account to check
         * @param blockNumber The block number to get the vote balance at
         * @return The number of votes the account had as of the given block
         */
        function getPriorVotes(address account, uint blockNumber)
            external
            view
            returns (uint256)
        {
            require(blockNumber < block.number, "NORI::getPriorVotes: not yet determined");
    
            uint32 nCheckpoints = numCheckpoints[account];
            if (nCheckpoints == 0) {
                return 0;
            }
    
            // First check most recent balance
            if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
                return checkpoints[account][nCheckpoints - 1].votes;
            }
    
            // Next check implicit zero balance
            if (checkpoints[account][0].fromBlock > blockNumber) {
                return 0;
            }
    
            uint32 lower = 0;
            uint32 upper = nCheckpoints - 1;
            while (upper > lower) {
                uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
                Checkpoint memory cp = checkpoints[account][center];
                if (cp.fromBlock == blockNumber) {
                    return cp.votes;
                } else if (cp.fromBlock < blockNumber) {
                    lower = center;
                } else {
                    upper = center - 1;
                }
            }
            return checkpoints[account][lower].votes;
        }
    
        function _delegate(address delegator, address delegatee)
            internal
        {
            address currentDelegate = _delegates[delegator];
            uint256 delegatorBalance = _noriBalances[delegator]; // balance of underlying NORIs (not scaled);
            _delegates[delegator] = delegatee;
    
            emit DelegateChanged(delegator, currentDelegate, delegatee);
    
            _moveDelegates(currentDelegate, delegatee, delegatorBalance);
        }
    
        function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
            if (srcRep != dstRep && amount > 0) {
                if (srcRep != address(0)) {
                    // decrease old representative
                    uint32 srcRepNum = numCheckpoints[srcRep];
                    uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                    uint256 srcRepNew = srcRepOld.sub(amount);
                    _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
                }
    
                if (dstRep != address(0)) {
                    // increase new representative
                    uint32 dstRepNum = numCheckpoints[dstRep];
                    uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                    uint256 dstRepNew = dstRepOld.add(amount);
                    _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
                }
            }
        }
    
        function _writeCheckpoint(
            address delegatee,
            uint32 nCheckpoints,
            uint256 oldVotes,
            uint256 newVotes
        )
            internal
        {
            uint32 blockNumber = safe32(block.number, "NORI::_writeCheckpoint: block number exceeds 32 bits");
    
            if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
                checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
            } else {
                checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
                numCheckpoints[delegatee] = nCheckpoints + 1;
            }
    
            emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
        }
    
        function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
            require(n < 2**32, errorMessage);
            return uint32(n);
        }
    
        function getChainId() internal pure returns (uint) {
            uint256 chainId;
            assembly { chainId := chainid() }
            return chainId;
        }
    }
    
    contract NORIToken is NORIGovernanceToken {
        // Modifiers
        modifier onlyGov() {
            require(msg.sender == gov);
            _;
        }
    
        modifier onlyRebaser() {
            require(msg.sender == rebaser);
            _;
        }
    
        modifier onlyMinter() {
            require(msg.sender == rebaser || msg.sender == incentivizer || msg.sender == gov, "not minter");
            _;
        }
    
        modifier validRecipient(address to) {
            require(to != address(0x0));
            require(to != address(this));
            _;
        }
    
        function initialize(
            string memory name_,
            string memory symbol_,
            uint8 decimals_
        )
            public
        {
            require(norisScalingFactor == 0, "already initialized");
            name = name_;
            symbol = symbol_;
            decimals = decimals_;
        }
    
    
        /**
        * @notice Computes the current max scaling factor
        */
        function maxScalingFactor()
            external
            view
            returns (uint256)
        {
            return _maxScalingFactor();
        }
    
        function _maxScalingFactor()
            internal
            view
            returns (uint256)
        {
            // scaling factor can only go up to 2**256-1 = initSupply * norisScalingFactor
            // this is used to check if norisScalingFactor will be too high to compute balances when rebasing.
            return uint256(-1) / initSupply;
        }
    
        /**
        * @notice Mints new tokens, increasing totalSupply, initSupply, and a users balance.
        * @dev Limited to onlyMinter modifier
        */
        function mint(address to, uint256 amount)
            external
            onlyMinter
            returns (bool)
        {
            _mint(to, amount);
            return true;
        }
    
        function _mint(address to, uint256 amount)
            internal
        {
          // increase totalSupply
          totalSupply = totalSupply.add(amount);
    
          // get underlying value
          uint256 noriValue = amount.mul(internalDecimals).div(norisScalingFactor);
    
          // increase initSupply
          initSupply = initSupply.add(noriValue);
    
          // make sure the mint didnt push maxScalingFactor too low
          require(norisScalingFactor <= _maxScalingFactor(), "max scaling factor too low");
    
          // add balance
          _noriBalances[to] = _noriBalances[to].add(noriValue);
    
          // add delegates to the minter
          _moveDelegates(address(0), _delegates[to], noriValue);
          emit Mint(to, amount);
        }
    
        /* - ERC20 functionality - */
    
        /**
        * @dev Transfer tokens to a specified address.
        * @param to The address to transfer to.
        * @param value The amount to be transferred.
        * @return True on success, false otherwise.
        */
        function transfer(address to, uint256 value)
            external
            validRecipient(to)
            returns (bool)
        {
            // underlying balance is stored in noris, so divide by current scaling factor
    
            // note, this means as scaling factor grows, dust will be untransferrable.
            // minimum transfer value == norisScalingFactor / 1e24;
    
            // get amount in underlying
            uint256 noriValue = value.mul(internalDecimals).div(norisScalingFactor);
    
            // sub from balance of sender
            _noriBalances[msg.sender] = _noriBalances[msg.sender].sub(noriValue);
    
            // add to balance of receiver
            _noriBalances[to] = _noriBalances[to].add(noriValue);
            emit Transfer(msg.sender, to, value);
    
            _moveDelegates(_delegates[msg.sender], _delegates[to], noriValue);
            return true;
        }
    
        /**
        * @dev Transfer tokens from one address to another.
        * @param from The address you want to send tokens from.
        * @param to The address you want to transfer to.
        * @param value The amount of tokens to be transferred.
        */
        function transferFrom(address from, address to, uint256 value)
            external
            validRecipient(to)
            returns (bool)
        {
            // decrease allowance
            _allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender].sub(value);
    
            // get value in noris
            uint256 noriValue = value.mul(internalDecimals).div(norisScalingFactor);
    
            // sub from from
            _noriBalances[from] = _noriBalances[from].sub(noriValue);
            _noriBalances[to] = _noriBalances[to].add(noriValue);
            emit Transfer(from, to, value);
    
            _moveDelegates(_delegates[from], _delegates[to], noriValue);
            return true;
        }
    
        /**
        * @param who The address to query.
        * @return The balance of the specified address.
        */
        function balanceOf(address who)
          external
          view
          returns (uint256)
        {
          return _noriBalances[who].mul(norisScalingFactor).div(internalDecimals);
        }
    
        /** @notice Currently returns the internal storage amount
        * @param who The address to query.
        * @return The underlying balance of the specified address.
        */
        function balanceOfUnderlying(address who)
          external
          view
          returns (uint256)
        {
          return _noriBalances[who];
        }
    
        /**
         * @dev Function to check the amount of tokens that an owner has allowed to a spender.
         * @param owner_ The address which owns the funds.
         * @param spender The address which will spend the funds.
         * @return The number of tokens still available for the spender.
         */
        function allowance(address owner_, address spender)
            external
            view
            returns (uint256)
        {
            return _allowedFragments[owner_][spender];
        }
    
        /**
         * @dev Approve the passed address to spend the specified amount of tokens on behalf of
         * msg.sender. This method is included for ERC20 compatibility.
         * increaseAllowance and decreaseAllowance should be used instead.
         * Changing an allowance with this method brings the risk that someone may transfer both
         * the old and the new allowance - if they are both greater than zero - if a transfer
         * transaction is mined before the later approve() call is mined.
         *
         * @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)
        {
            _allowedFragments[msg.sender][spender] = value;
            emit Approval(msg.sender, spender, value);
            return true;
        }
    
        /**
         * @dev Increase the amount of tokens that an owner has allowed to a spender.
         * This method should be used instead of approve() to avoid the double approval vulnerability
         * described above.
         * @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)
            external
            returns (bool)
        {
            _allowedFragments[msg.sender][spender] =
                _allowedFragments[msg.sender][spender].add(addedValue);
            emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
            return true;
        }
    
        /**
         * @dev Decrease the amount of tokens that an owner has allowed to a spender.
         *
         * @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)
            external
            returns (bool)
        {
            uint256 oldValue = _allowedFragments[msg.sender][spender];
            if (subtractedValue >= oldValue) {
                _allowedFragments[msg.sender][spender] = 0;
            } else {
                _allowedFragments[msg.sender][spender] = oldValue.sub(subtractedValue);
            }
            emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
            return true;
        }
    
        /* - Governance Functions - */
    
        /** @notice sets the rebaser
         * @param rebaser_ The address of the rebaser contract to use for authentication.
         */
        function _setRebaser(address rebaser_)
            external
            onlyGov
        {
            address oldRebaser = rebaser;
            rebaser = rebaser_;
            emit NewRebaser(oldRebaser, rebaser_);
        }
    
        /** @notice sets the incentivizer
         * @param incentivizer_ The address of the rebaser contract to use for authentication.
         */
        function _setIncentivizer(address incentivizer_)
            external
            onlyGov
        {
            address oldIncentivizer = incentivizer;
            incentivizer = incentivizer_;
            emit NewIncentivizer(oldIncentivizer, incentivizer_);
        }
    
        /** @notice sets the pendingGov
         * @param pendingGov_ The address of the rebaser contract to use for authentication.
         */
        function _setPendingGov(address pendingGov_)
            external
            onlyGov
        {
            address oldPendingGov = pendingGov;
            pendingGov = pendingGov_;
            emit NewPendingGov(oldPendingGov, pendingGov_);
        }
    
        /** @notice lets msg.sender accept governance
         *
         */
        function _acceptGov()
            external
        {
            require(msg.sender == pendingGov, "!pending");
            address oldGov = gov;
            gov = pendingGov;
            pendingGov = address(0);
            emit NewGov(oldGov, gov);
        }
    
        /* - Extras - */
    
        /**
        * @notice Initiates a new rebase operation, provided the minimum time period has elapsed.
        *
        * @dev The supply adjustment equals (totalSupply * DeviationFromTargetRate) / rebaseLag
        *      Where DeviationFromTargetRate is (MarketOracleRate - targetRate) / targetRate
        *      and targetRate is CpiOracleRate / baseCpi
        */
        function rebase(
            uint256 epoch,
            uint256 indexDelta,
            bool positive
        )
            external
            onlyRebaser
            returns (uint256)
        {
            if (indexDelta == 0) {
              emit Rebase(epoch, norisScalingFactor, norisScalingFactor);
              return totalSupply;
            }
    
            uint256 prevNorisScalingFactor = norisScalingFactor;
    
            if (!positive) {
               norisScalingFactor = norisScalingFactor.mul(BASE.sub(indexDelta)).div(BASE);
            } else {
                uint256 newScalingFactor = norisScalingFactor.mul(BASE.add(indexDelta)).div(BASE);
                if (newScalingFactor < _maxScalingFactor()) {
                    norisScalingFactor = newScalingFactor;
                } else {
                  norisScalingFactor = _maxScalingFactor();
                }
            }
    
            totalSupply = initSupply.mul(norisScalingFactor);
            emit Rebase(epoch, prevNorisScalingFactor, norisScalingFactor);
            return totalSupply;
        }
    }
    
    contract NORI is NORIToken {
        /**
         * @notice Initialize the new money market
         * @param name_ ERC-20 name of this token
         * @param symbol_ ERC-20 symbol of this token
         * @param decimals_ ERC-20 decimal precision of this token
         */
        function initialize(
            string memory name_,
            string memory symbol_,
            uint8 decimals_,
            address initial_owner,
            uint256 initSupply_
        )
            public
        {
            require(initSupply_ > 0, "0 init supply");
    
            super.initialize(name_, symbol_, decimals_);
    
            initSupply = initSupply_.mul(10**24/ (BASE));
            totalSupply = initSupply_;
            norisScalingFactor = BASE;
            _noriBalances[initial_owner] = initSupply_.mul(10**24 / (BASE));
    
            // owner renounces ownership after deployment as they need to set
            // rebaser and incentivizer
            // gov = gov_;
        }
    }
    
    
    contract NORIDelegationStorage {
        /**
         * @notice Implementation address for this contract
         */
        address public implementation;
    }
    
    contract NORIDelegatorInterface is NORIDelegationStorage {
        /**
         * @notice Emitted when implementation is changed
         */
        event NewImplementation(address oldImplementation, address newImplementation);
    
        /**
         * @notice Called by the gov to update the implementation of the delegator
         * @param implementation_ The address of the new implementation for delegation
         * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
         * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
         */
        function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) public;
    }
    
    contract NORIDelegateInterface is NORIDelegationStorage {
        /**
         * @notice Called by the delegator on a delegate to initialize it for duty
         * @dev Should revert if any issues arise which make it unfit for delegation
         * @param data The encoded bytes data for any initialization
         */
        function _becomeImplementation(bytes memory data) public;
    
        /**
         * @notice Called by the delegator on a delegate to forfeit its responsibility
         */
        function _resignImplementation() public;
    }
    
    
    contract NORIDelegate is NORI, NORIDelegateInterface {
        /**
         * @notice Construct an empty delegate
         */
        constructor() public {}
    
        /**
         * @notice Called by the delegator on a delegate to initialize it for duty
         * @param data The encoded bytes data for any initialization
         */
        function _becomeImplementation(bytes memory data) public {
            // Shh -- currently unused
            data;
    
            // Shh -- we don't ever want this hook to be marked pure
            if (false) {
                implementation = address(0);
            }
    
            require(msg.sender == gov, "only the gov may call _becomeImplementation");
        }
    
        /**
         * @notice Called by the delegator on a delegate to forfeit its responsibility
         */
        function _resignImplementation() public {
            // Shh -- we don't ever want this hook to be marked pure
            if (false) {
                implementation = address(0);
            }
    
            require(msg.sender == gov, "only the gov may call _resignImplementation");
        }
    }