ETH Price: $3,811.91 (+1.42%)
Gas: 4 Gwei

Transaction Decoder

Block:
19814702 at May-07-2024 12:45:11 AM +UTC
Transaction Fee:
0.000468465429946478 ETH $1.79
Gas Used:
132,733 Gas / 3.529381766 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
(Titan Builder)
10.048075569830457919 Eth10.048092860714935597 Eth0.000017290884477678
0x5A98FcBE...A3beF1B32
0x96d26606...7242cC051
0.001360672380219716 Eth
Nonce: 64
0.000892206950273238 Eth
Nonce: 65
0.000468465429946478

Execution Trace

MiniMeToken.transfer( _to=0xCFFAd3200574698b78f32232aa9D63eABD290703, _amount=164354908113949232874 ) => ( success=True )
  • AppProxyUpgradeable.4a393149( )
    • KernelProxy.be00bbd8( )
      • Kernel.getApp( _namespace=F1F3EB40F5BC1AD1344716CED8B8A0431D840B5783AEA1FD01786BC26F35AC0F, _appId=CD567BDF93DD0F6ACC3BC7F2155F83244D56A65ABBFBEFB763E015420102C67B ) => ( 0xde3A93028F2283cc28756B3674BD657eaFB992f4 )
      • TokenManager.onTransfer( _from=0x96d266067291C4B7a3FD90fCB070d417242cC051, _to=0xCFFAd3200574698b78f32232aa9D63eABD290703, _amount=164354908113949232874 ) => ( True )
        • MiniMeToken.balanceOf( _owner=0xCFFAd3200574698b78f32232aa9D63eABD290703 ) => ( balance=605293619650146840605474 )
        • MiniMeToken.balanceOf( _owner=0x96d266067291C4B7a3FD90fCB070d417242cC051 ) => ( balance=164354908113949232874 )
          File 1 of 5: MiniMeToken
          pragma solidity ^0.4.24;
          // File: @aragon/apps-shared-minime/contracts/ITokenController.sol
          /// @dev The token controller contract must implement these functions
          
          
          interface ITokenController {
              /// @notice Called when `_owner` sends ether to the MiniMe Token contract
              /// @param _owner The address that sent the ether to create tokens
              /// @return True if the ether is accepted, false if it throws
              function proxyPayment(address _owner) external payable returns(bool);
          
              /// @notice Notifies the controller about a token transfer allowing the
              ///  controller to react if desired
              /// @param _from The origin of the transfer
              /// @param _to The destination of the transfer
              /// @param _amount The amount of the transfer
              /// @return False if the controller does not authorize the transfer
              function onTransfer(address _from, address _to, uint _amount) external returns(bool);
          
              /// @notice Notifies the controller about an approval allowing the
              ///  controller to react if desired
              /// @param _owner The address that calls `approve()`
              /// @param _spender The spender in the `approve()` call
              /// @param _amount The amount in the `approve()` call
              /// @return False if the controller does not authorize the approval
              function onApprove(address _owner, address _spender, uint _amount) external returns(bool);
          }
          // File: @aragon/apps-shared-minime/contracts/MiniMeToken.sol
          /*
              Copyright 2016, Jordi Baylina
              This program is free software: you can redistribute it and/or modify
              it under the terms of the GNU General Public License as published by
              the Free Software Foundation, either version 3 of the License, or
              (at your option) any later version.
              This program is distributed in the hope that it will be useful,
              but WITHOUT ANY WARRANTY; without even the implied warranty of
              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
              GNU General Public License for more details.
              You should have received a copy of the GNU General Public License
              along with this program.  If not, see <http://www.gnu.org/licenses/>.
           */
          
          /// @title MiniMeToken Contract
          /// @author Jordi Baylina
          /// @dev This token contract's goal is to make it easy for anyone to clone this
          ///  token using the token distribution at a given block, this will allow DAO's
          ///  and DApps to upgrade their features in a decentralized manner without
          ///  affecting the original token
          /// @dev It is ERC20 compliant, but still needs to under go further testing.
          
          
          contract Controlled {
              /// @notice The address of the controller is the only address that can call
              ///  a function with this modifier
              modifier onlyController {
                  require(msg.sender == controller);
                  _;
              }
          
              address public controller;
          
              function Controlled()  public { controller = msg.sender;}
          
              /// @notice Changes the controller of the contract
              /// @param _newController The new controller of the contract
              function changeController(address _newController) onlyController  public {
                  controller = _newController;
              }
          }
          
          contract ApproveAndCallFallBack {
              function receiveApproval(
                  address from,
                  uint256 _amount,
                  address _token,
                  bytes _data
              ) public;
          }
          
          /// @dev The actual token contract, the default controller is the msg.sender
          ///  that deploys the contract, so usually this token will be deployed by a
          ///  token controller contract, which Giveth will call a "Campaign"
          contract MiniMeToken is Controlled {
          
              string public name;                //The Token's name: e.g. DigixDAO Tokens
              uint8 public decimals;             //Number of decimals of the smallest unit
              string public symbol;              //An identifier: e.g. REP
              string public version = "MMT_0.1"; //An arbitrary versioning scheme
          
          
              /// @dev `Checkpoint` is the structure that attaches a block number to a
              ///  given value, the block number attached is the one that last changed the
              ///  value
              struct Checkpoint {
          
                  // `fromBlock` is the block number that the value was generated from
                  uint128 fromBlock;
          
                  // `value` is the amount of tokens at a specific block number
                  uint128 value;
              }
          
              // `parentToken` is the Token address that was cloned to produce this token;
              //  it will be 0x0 for a token that was not cloned
              MiniMeToken public parentToken;
          
              // `parentSnapShotBlock` is the block number from the Parent Token that was
              //  used to determine the initial distribution of the Clone Token
              uint public parentSnapShotBlock;
          
              // `creationBlock` is the block number that the Clone Token was created
              uint public creationBlock;
          
              // `balances` is the map that tracks the balance of each address, in this
              //  contract when the balance changes the block number that the change
              //  occurred is also included in the map
              mapping (address => Checkpoint[]) balances;
          
              // `allowed` tracks any extra transfer rights as in all ERC20 tokens
              mapping (address => mapping (address => uint256)) allowed;
          
              // Tracks the history of the `totalSupply` of the token
              Checkpoint[] totalSupplyHistory;
          
              // Flag that determines if the token is transferable or not.
              bool public transfersEnabled;
          
              // The factory used to create new clone tokens
              MiniMeTokenFactory public tokenFactory;
          
          ////////////////
          // Constructor
          ////////////////
          
              /// @notice Constructor to create a MiniMeToken
              /// @param _tokenFactory The address of the MiniMeTokenFactory contract that
              ///  will create the Clone token contracts, the token factory needs to be
              ///  deployed first
              /// @param _parentToken Address of the parent token, set to 0x0 if it is a
              ///  new token
              /// @param _parentSnapShotBlock Block of the parent token that will
              ///  determine the initial distribution of the clone token, set to 0 if it
              ///  is a new token
              /// @param _tokenName Name of the new token
              /// @param _decimalUnits Number of decimals of the new token
              /// @param _tokenSymbol Token Symbol for the new token
              /// @param _transfersEnabled If true, tokens will be able to be transferred
              function MiniMeToken(
                  MiniMeTokenFactory _tokenFactory,
                  MiniMeToken _parentToken,
                  uint _parentSnapShotBlock,
                  string _tokenName,
                  uint8 _decimalUnits,
                  string _tokenSymbol,
                  bool _transfersEnabled
              )  public
              {
                  tokenFactory = _tokenFactory;
                  name = _tokenName;                                 // Set the name
                  decimals = _decimalUnits;                          // Set the decimals
                  symbol = _tokenSymbol;                             // Set the symbol
                  parentToken = _parentToken;
                  parentSnapShotBlock = _parentSnapShotBlock;
                  transfersEnabled = _transfersEnabled;
                  creationBlock = block.number;
              }
          
          
          ///////////////////
          // ERC20 Methods
          ///////////////////
          
              /// @notice Send `_amount` tokens to `_to` from `msg.sender`
              /// @param _to The address of the recipient
              /// @param _amount The amount of tokens to be transferred
              /// @return Whether the transfer was successful or not
              function transfer(address _to, uint256 _amount) public returns (bool success) {
                  require(transfersEnabled);
                  return doTransfer(msg.sender, _to, _amount);
              }
          
              /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
              ///  is approved by `_from`
              /// @param _from The address holding the tokens being transferred
              /// @param _to The address of the recipient
              /// @param _amount The amount of tokens to be transferred
              /// @return True if the transfer was successful
              function transferFrom(address _from, address _to, uint256 _amount) public returns (bool success) {
          
                  // The controller of this contract can move tokens around at will,
                  //  this is important to recognize! Confirm that you trust the
                  //  controller of this contract, which in most situations should be
                  //  another open source smart contract or 0x0
                  if (msg.sender != controller) {
                      require(transfersEnabled);
          
                      // The standard ERC 20 transferFrom functionality
                      if (allowed[_from][msg.sender] < _amount)
                          return false;
                      allowed[_from][msg.sender] -= _amount;
                  }
                  return doTransfer(_from, _to, _amount);
              }
          
              /// @dev This is the actual transfer function in the token contract, it can
              ///  only be called by other functions in this contract.
              /// @param _from The address holding the tokens being transferred
              /// @param _to The address of the recipient
              /// @param _amount The amount of tokens to be transferred
              /// @return True if the transfer was successful
              function doTransfer(address _from, address _to, uint _amount) internal returns(bool) {
                  if (_amount == 0) {
                      return true;
                  }
                  require(parentSnapShotBlock < block.number);
                  // Do not allow transfer to 0x0 or the token contract itself
                  require((_to != 0) && (_to != address(this)));
                  // If the amount being transfered is more than the balance of the
                  //  account the transfer returns false
                  var previousBalanceFrom = balanceOfAt(_from, block.number);
                  if (previousBalanceFrom < _amount) {
                      return false;
                  }
                  // Alerts the token controller of the transfer
                  if (isContract(controller)) {
                      // Adding the ` == true` makes the linter shut up so...
                      require(ITokenController(controller).onTransfer(_from, _to, _amount) == true);
                  }
                  // First update the balance array with the new value for the address
                  //  sending the tokens
                  updateValueAtNow(balances[_from], previousBalanceFrom - _amount);
                  // Then update the balance array with the new value for the address
                  //  receiving the tokens
                  var previousBalanceTo = balanceOfAt(_to, block.number);
                  require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
                  updateValueAtNow(balances[_to], previousBalanceTo + _amount);
                  // An event to make the transfer easy to find on the blockchain
                  Transfer(_from, _to, _amount);
                  return true;
              }
          
              /// @param _owner The address that's balance is being requested
              /// @return The balance of `_owner` at the current block
              function balanceOf(address _owner) public constant returns (uint256 balance) {
                  return balanceOfAt(_owner, block.number);
              }
          
              /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
              ///  its behalf. This is a modified version of the ERC20 approve function
              ///  to be a little bit safer
              /// @param _spender The address of the account able to transfer the tokens
              /// @param _amount The amount of tokens to be approved for transfer
              /// @return True if the approval was successful
              function approve(address _spender, uint256 _amount) public returns (bool success) {
                  require(transfersEnabled);
          
                  // To change the approve amount you first have to reduce the addresses`
                  //  allowance to zero by calling `approve(_spender,0)` if it is not
                  //  already 0 to mitigate the race condition described here:
                  //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                  require((_amount == 0) || (allowed[msg.sender][_spender] == 0));
          
                  // Alerts the token controller of the approve function call
                  if (isContract(controller)) {
                      // Adding the ` == true` makes the linter shut up so...
                      require(ITokenController(controller).onApprove(msg.sender, _spender, _amount) == true);
                  }
          
                  allowed[msg.sender][_spender] = _amount;
                  Approval(msg.sender, _spender, _amount);
                  return true;
              }
          
              /// @dev This function makes it easy to read the `allowed[]` map
              /// @param _owner The address of the account that owns the token
              /// @param _spender The address of the account able to transfer the tokens
              /// @return Amount of remaining tokens of _owner that _spender is allowed
              ///  to spend
              function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
                  return allowed[_owner][_spender];
              }
          
              /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
              ///  its behalf, and then a function is triggered in the contract that is
              ///  being approved, `_spender`. This allows users to use their tokens to
              ///  interact with contracts in one function call instead of two
              /// @param _spender The address of the contract able to transfer the tokens
              /// @param _amount The amount of tokens to be approved for transfer
              /// @return True if the function call was successful
              function approveAndCall(ApproveAndCallFallBack _spender, uint256 _amount, bytes _extraData) public returns (bool success) {
                  require(approve(_spender, _amount));
          
                  _spender.receiveApproval(
                      msg.sender,
                      _amount,
                      this,
                      _extraData
                  );
          
                  return true;
              }
          
              /// @dev This function makes it easy to get the total number of tokens
              /// @return The total number of tokens
              function totalSupply() public constant returns (uint) {
                  return totalSupplyAt(block.number);
              }
          
          
          ////////////////
          // Query balance and totalSupply in History
          ////////////////
          
              /// @dev Queries the balance of `_owner` at a specific `_blockNumber`
              /// @param _owner The address from which the balance will be retrieved
              /// @param _blockNumber The block number when the balance is queried
              /// @return The balance at `_blockNumber`
              function balanceOfAt(address _owner, uint _blockNumber) public constant returns (uint) {
          
                  // These next few lines are used when the balance of the token is
                  //  requested before a check point was ever created for this token, it
                  //  requires that the `parentToken.balanceOfAt` be queried at the
                  //  genesis block for that token as this contains initial balance of
                  //  this token
                  if ((balances[_owner].length == 0) || (balances[_owner][0].fromBlock > _blockNumber)) {
                      if (address(parentToken) != 0) {
                          return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock));
                      } else {
                          // Has no parent
                          return 0;
                      }
          
                  // This will return the expected balance during normal situations
                  } else {
                      return getValueAt(balances[_owner], _blockNumber);
                  }
              }
          
              /// @notice Total amount of tokens at a specific `_blockNumber`.
              /// @param _blockNumber The block number when the totalSupply is queried
              /// @return The total amount of tokens at `_blockNumber`
              function totalSupplyAt(uint _blockNumber) public constant returns(uint) {
          
                  // These next few lines are used when the totalSupply of the token is
                  //  requested before a check point was ever created for this token, it
                  //  requires that the `parentToken.totalSupplyAt` be queried at the
                  //  genesis block for this token as that contains totalSupply of this
                  //  token at this block number.
                  if ((totalSupplyHistory.length == 0) || (totalSupplyHistory[0].fromBlock > _blockNumber)) {
                      if (address(parentToken) != 0) {
                          return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock));
                      } else {
                          return 0;
                      }
          
                  // This will return the expected totalSupply during normal situations
                  } else {
                      return getValueAt(totalSupplyHistory, _blockNumber);
                  }
              }
          
          ////////////////
          // Clone Token Method
          ////////////////
          
              /// @notice Creates a new clone token with the initial distribution being
              ///  this token at `_snapshotBlock`
              /// @param _cloneTokenName Name of the clone token
              /// @param _cloneDecimalUnits Number of decimals of the smallest unit
              /// @param _cloneTokenSymbol Symbol of the clone token
              /// @param _snapshotBlock Block when the distribution of the parent token is
              ///  copied to set the initial distribution of the new clone token;
              ///  if the block is zero than the actual block, the current block is used
              /// @param _transfersEnabled True if transfers are allowed in the clone
              /// @return The address of the new MiniMeToken Contract
              function createCloneToken(
                  string _cloneTokenName,
                  uint8 _cloneDecimalUnits,
                  string _cloneTokenSymbol,
                  uint _snapshotBlock,
                  bool _transfersEnabled
              ) public returns(MiniMeToken)
              {
                  uint256 snapshot = _snapshotBlock == 0 ? block.number - 1 : _snapshotBlock;
          
                  MiniMeToken cloneToken = tokenFactory.createCloneToken(
                      this,
                      snapshot,
                      _cloneTokenName,
                      _cloneDecimalUnits,
                      _cloneTokenSymbol,
                      _transfersEnabled
                  );
          
                  cloneToken.changeController(msg.sender);
          
                  // An event to make the token easy to find on the blockchain
                  NewCloneToken(address(cloneToken), snapshot);
                  return cloneToken;
              }
          
          ////////////////
          // Generate and destroy tokens
          ////////////////
          
              /// @notice Generates `_amount` tokens that are assigned to `_owner`
              /// @param _owner The address that will be assigned the new tokens
              /// @param _amount The quantity of tokens generated
              /// @return True if the tokens are generated correctly
              function generateTokens(address _owner, uint _amount) onlyController public returns (bool) {
                  uint curTotalSupply = totalSupply();
                  require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow
                  uint previousBalanceTo = balanceOf(_owner);
                  require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
                  updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
                  updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
                  Transfer(0, _owner, _amount);
                  return true;
              }
          
          
              /// @notice Burns `_amount` tokens from `_owner`
              /// @param _owner The address that will lose the tokens
              /// @param _amount The quantity of tokens to burn
              /// @return True if the tokens are burned correctly
              function destroyTokens(address _owner, uint _amount) onlyController public returns (bool) {
                  uint curTotalSupply = totalSupply();
                  require(curTotalSupply >= _amount);
                  uint previousBalanceFrom = balanceOf(_owner);
                  require(previousBalanceFrom >= _amount);
                  updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
                  updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
                  Transfer(_owner, 0, _amount);
                  return true;
              }
          
          ////////////////
          // Enable tokens transfers
          ////////////////
          
          
              /// @notice Enables token holders to transfer their tokens freely if true
              /// @param _transfersEnabled True if transfers are allowed in the clone
              function enableTransfers(bool _transfersEnabled) onlyController public {
                  transfersEnabled = _transfersEnabled;
              }
          
          ////////////////
          // Internal helper functions to query and set a value in a snapshot array
          ////////////////
          
              /// @dev `getValueAt` retrieves the number of tokens at a given block number
              /// @param checkpoints The history of values being queried
              /// @param _block The block number to retrieve the value at
              /// @return The number of tokens being queried
              function getValueAt(Checkpoint[] storage checkpoints, uint _block) constant internal returns (uint) {
                  if (checkpoints.length == 0)
                      return 0;
          
                  // Shortcut for the actual value
                  if (_block >= checkpoints[checkpoints.length-1].fromBlock)
                      return checkpoints[checkpoints.length-1].value;
                  if (_block < checkpoints[0].fromBlock)
                      return 0;
          
                  // Binary search of the value in the array
                  uint min = 0;
                  uint max = checkpoints.length-1;
                  while (max > min) {
                      uint mid = (max + min + 1) / 2;
                      if (checkpoints[mid].fromBlock<=_block) {
                          min = mid;
                      } else {
                          max = mid-1;
                      }
                  }
                  return checkpoints[min].value;
              }
          
              /// @dev `updateValueAtNow` used to update the `balances` map and the
              ///  `totalSupplyHistory`
              /// @param checkpoints The history of data being updated
              /// @param _value The new number of tokens
              function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value) internal {
                  if ((checkpoints.length == 0) || (checkpoints[checkpoints.length - 1].fromBlock < block.number)) {
                      Checkpoint storage newCheckPoint = checkpoints[checkpoints.length++];
                      newCheckPoint.fromBlock = uint128(block.number);
                      newCheckPoint.value = uint128(_value);
                  } else {
                      Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length - 1];
                      oldCheckPoint.value = uint128(_value);
                  }
              }
          
              /// @dev Internal function to determine if an address is a contract
              /// @param _addr The address being queried
              /// @return True if `_addr` is a contract
              function isContract(address _addr) constant internal returns(bool) {
                  uint size;
                  if (_addr == 0)
                      return false;
          
                  assembly {
                      size := extcodesize(_addr)
                  }
          
                  return size>0;
              }
          
              /// @dev Helper function to return a min betwen the two uints
              function min(uint a, uint b) pure internal returns (uint) {
                  return a < b ? a : b;
              }
          
              /// @notice The fallback function: If the contract's controller has not been
              ///  set to 0, then the `proxyPayment` method is called which relays the
              ///  ether and creates tokens as described in the token controller contract
              function () external payable {
                  require(isContract(controller));
                  // Adding the ` == true` makes the linter shut up so...
                  require(ITokenController(controller).proxyPayment.value(msg.value)(msg.sender) == true);
              }
          
          //////////
          // Safety Methods
          //////////
          
              /// @notice This method can be used by the controller to extract mistakenly
              ///  sent tokens to this contract.
              /// @param _token The address of the token contract that you want to recover
              ///  set to 0 in case you want to extract ether.
              function claimTokens(address _token) onlyController public {
                  if (_token == 0x0) {
                      controller.transfer(this.balance);
                      return;
                  }
          
                  MiniMeToken token = MiniMeToken(_token);
                  uint balance = token.balanceOf(this);
                  token.transfer(controller, balance);
                  ClaimedTokens(_token, controller, balance);
              }
          
          ////////////////
          // Events
          ////////////////
              event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
              event Transfer(address indexed _from, address indexed _to, uint256 _amount);
              event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
              event Approval(
                  address indexed _owner,
                  address indexed _spender,
                  uint256 _amount
                  );
          
          }
          
          
          ////////////////
          // MiniMeTokenFactory
          ////////////////
          
          /// @dev This contract is used to generate clone contracts from a contract.
          ///  In solidity this is the way to create a contract from a contract of the
          ///  same class
          contract MiniMeTokenFactory {
          
              /// @notice Update the DApp by creating a new token with new functionalities
              ///  the msg.sender becomes the controller of this clone token
              /// @param _parentToken Address of the token being cloned
              /// @param _snapshotBlock Block of the parent token that will
              ///  determine the initial distribution of the clone token
              /// @param _tokenName Name of the new token
              /// @param _decimalUnits Number of decimals of the new token
              /// @param _tokenSymbol Token Symbol for the new token
              /// @param _transfersEnabled If true, tokens will be able to be transferred
              /// @return The address of the new token contract
              function createCloneToken(
                  MiniMeToken _parentToken,
                  uint _snapshotBlock,
                  string _tokenName,
                  uint8 _decimalUnits,
                  string _tokenSymbol,
                  bool _transfersEnabled
              ) public returns (MiniMeToken)
              {
                  MiniMeToken newToken = new MiniMeToken(
                      this,
                      _parentToken,
                      _snapshotBlock,
                      _tokenName,
                      _decimalUnits,
                      _tokenSymbol,
                      _transfersEnabled
                  );
          
                  newToken.changeController(msg.sender);
                  return newToken;
              }
          }

          File 2 of 5: AppProxyUpgradeable
          // File: contracts/common/UnstructuredStorage.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          library UnstructuredStorage {
              function getStorageBool(bytes32 position) internal view returns (bool data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageAddress(bytes32 position) internal view returns (address data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageUint256(bytes32 position) internal view returns (uint256 data) {
                  assembly { data := sload(position) }
              }
          
              function setStorageBool(bytes32 position, bool data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageAddress(bytes32 position, address data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageBytes32(bytes32 position, bytes32 data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageUint256(bytes32 position, uint256 data) internal {
                  assembly { sstore(position, data) }
              }
          }
          
          // File: contracts/acl/IACL.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IACL {
              function initialize(address permissionsCreator) external;
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          }
          
          // File: contracts/common/IVaultRecoverable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IVaultRecoverable {
              event RecoverToVault(address indexed vault, address indexed token, uint256 amount);
          
              function transferToVault(address token) external;
          
              function allowRecoverability(address token) external view returns (bool);
              function getRecoveryVault() external view returns (address);
          }
          
          // File: contracts/kernel/IKernel.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          interface IKernelEvents {
              event SetApp(bytes32 indexed namespace, bytes32 indexed appId, address app);
          }
          
          
          // This should be an interface, but interfaces can't inherit yet :(
          contract IKernel is IKernelEvents, IVaultRecoverable {
              function acl() public view returns (IACL);
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          
              function setApp(bytes32 namespace, bytes32 appId, address app) public;
              function getApp(bytes32 namespace, bytes32 appId) public view returns (address);
          }
          
          // File: contracts/apps/AppStorage.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract AppStorage {
              using UnstructuredStorage for bytes32;
          
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_POSITION = keccak256("aragonOS.appStorage.kernel");
              bytes32 internal constant APP_ID_POSITION = keccak256("aragonOS.appStorage.appId");
              */
              bytes32 internal constant KERNEL_POSITION = 0x4172f0f7d2289153072b0a6ca36959e0cbe2efc3afe50fc81636caa96338137b;
              bytes32 internal constant APP_ID_POSITION = 0xd625496217aa6a3453eecb9c3489dc5a53e6c67b444329ea2b2cbc9ff547639b;
          
              function kernel() public view returns (IKernel) {
                  return IKernel(KERNEL_POSITION.getStorageAddress());
              }
          
              function appId() public view returns (bytes32) {
                  return APP_ID_POSITION.getStorageBytes32();
              }
          
              function setKernel(IKernel _kernel) internal {
                  KERNEL_POSITION.setStorageAddress(address(_kernel));
              }
          
              function setAppId(bytes32 _appId) internal {
                  APP_ID_POSITION.setStorageBytes32(_appId);
              }
          }
          
          // File: contracts/common/IsContract.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract IsContract {
              /*
              * NOTE: this should NEVER be used for authentication
              * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize).
              *
              * This is only intended to be used as a sanity check that an address is actually a contract,
              * RATHER THAN an address not being a contract.
              */
              function isContract(address _target) internal view returns (bool) {
                  if (_target == address(0)) {
                      return false;
                  }
          
                  uint256 size;
                  assembly { size := extcodesize(_target) }
                  return size > 0;
              }
          }
          
          // File: contracts/lib/misc/ERCProxy.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract ERCProxy {
              uint256 internal constant FORWARDING = 1;
              uint256 internal constant UPGRADEABLE = 2;
          
              function proxyType() public pure returns (uint256 proxyTypeId);
              function implementation() public view returns (address codeAddr);
          }
          
          // File: contracts/common/DelegateProxy.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract DelegateProxy is ERCProxy, IsContract {
              uint256 internal constant FWD_GAS_LIMIT = 10000;
          
              /**
              * @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!)
              * @param _dst Destination address to perform the delegatecall
              * @param _calldata Calldata for the delegatecall
              */
              function delegatedFwd(address _dst, bytes _calldata) internal {
                  require(isContract(_dst));
                  uint256 fwdGasLimit = FWD_GAS_LIMIT;
          
                  assembly {
                      let result := delegatecall(sub(gas, fwdGasLimit), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0)
                      let size := returndatasize
                      let ptr := mload(0x40)
                      returndatacopy(ptr, 0, size)
          
                      // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas.
                      // if the call returned error data, forward it
                      switch result case 0 { revert(ptr, size) }
                      default { return(ptr, size) }
                  }
              }
          }
          
          // File: contracts/common/DepositableStorage.sol
          
          pragma solidity 0.4.24;
          
          
          
          contract DepositableStorage {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.depositableStorage.depositable")
              bytes32 internal constant DEPOSITABLE_POSITION = 0x665fd576fbbe6f247aff98f5c94a561e3f71ec2d3c988d56f12d342396c50cea;
          
              function isDepositable() public view returns (bool) {
                  return DEPOSITABLE_POSITION.getStorageBool();
              }
          
              function setDepositable(bool _depositable) internal {
                  DEPOSITABLE_POSITION.setStorageBool(_depositable);
              }
          }
          
          // File: contracts/common/DepositableDelegateProxy.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract DepositableDelegateProxy is DepositableStorage, DelegateProxy {
              event ProxyDeposit(address sender, uint256 value);
          
              function () external payable {
                  uint256 forwardGasThreshold = FWD_GAS_LIMIT;
                  bytes32 isDepositablePosition = DEPOSITABLE_POSITION;
          
                  // Optimized assembly implementation to prevent EIP-1884 from breaking deposits, reference code in Solidity:
                  // https://github.com/aragon/aragonOS/blob/v4.2.1/contracts/common/DepositableDelegateProxy.sol#L10-L20
                  assembly {
                      // Continue only if the gas left is lower than the threshold for forwarding to the implementation code,
                      // otherwise continue outside of the assembly block.
                      if lt(gas, forwardGasThreshold) {
                          // Only accept the deposit and emit an event if all of the following are true:
                          // the proxy accepts deposits (isDepositable), msg.data.length == 0, and msg.value > 0
                          if and(and(sload(isDepositablePosition), iszero(calldatasize)), gt(callvalue, 0)) {
                              // Equivalent Solidity code for emitting the event:
                              // emit ProxyDeposit(msg.sender, msg.value);
          
                              let logData := mload(0x40) // free memory pointer
                              mstore(logData, caller) // add 'msg.sender' to the log data (first event param)
                              mstore(add(logData, 0x20), callvalue) // add 'msg.value' to the log data (second event param)
          
                              // Emit an event with one topic to identify the event: keccak256('ProxyDeposit(address,uint256)') = 0x15ee...dee1
                              log1(logData, 0x40, 0x15eeaa57c7bd188c1388020bcadc2c436ec60d647d36ef5b9eb3c742217ddee1)
          
                              stop() // Stop. Exits execution context
                          }
          
                          // If any of above checks failed, revert the execution (if ETH was sent, it is returned to the sender)
                          revert(0, 0)
                      }
                  }
          
                  address target = implementation();
                  delegatedFwd(target, msg.data);
              }
          }
          
          // File: contracts/kernel/KernelConstants.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract KernelAppIds {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_APP_ID = apmNamehash("kernel");
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = apmNamehash("acl");
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = apmNamehash("vault");
              */
              bytes32 internal constant KERNEL_CORE_APP_ID = 0x3b4bf6bf3ad5000ecf0f989d5befde585c6860fea3e574a4fab4c49d1c177d9c;
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = 0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a;
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = 0x7e852e0fcfce6551c13800f1e7476f982525c2b5277ba14b24339c68416336d1;
          }
          
          
          contract KernelNamespaceConstants {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_NAMESPACE = keccak256("core");
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = keccak256("base");
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = keccak256("app");
              */
              bytes32 internal constant KERNEL_CORE_NAMESPACE = 0xc681a85306374a5ab27f0bbc385296a54bcd314a1948b6cf61c4ea1bc44bb9f8;
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = 0xf1f3eb40f5bc1ad1344716ced8b8a0431d840b5783aea1fd01786bc26f35ac0f;
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
          }
          
          // File: contracts/apps/AppProxyBase.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          contract AppProxyBase is AppStorage, DepositableDelegateProxy, KernelNamespaceConstants {
              /**
              * @dev Initialize AppProxy
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload) public {
                  setKernel(_kernel);
                  setAppId(_appId);
          
                  // Implicit check that kernel is actually a Kernel
                  // The EVM doesn't actually provide a way for us to make sure, but we can force a revert to
                  // occur if the kernel is set to 0x0 or a non-code address when we try to call a method on
                  // it.
                  address appCode = getAppBase(_appId);
          
                  // If initialize payload is provided, it will be executed
                  if (_initializePayload.length > 0) {
                      require(isContract(appCode));
                      // Cannot make delegatecall as a delegateproxy.delegatedFwd as it
                      // returns ending execution context and halts contract deployment
                      require(appCode.delegatecall(_initializePayload));
                  }
              }
          
              function getAppBase(bytes32 _appId) internal view returns (address) {
                  return kernel().getApp(KERNEL_APP_BASES_NAMESPACE, _appId);
              }
          }
          
          // File: contracts/apps/AppProxyUpgradeable.sol
          
          pragma solidity 0.4.24;
          
          
          
          contract AppProxyUpgradeable is AppProxyBase {
              /**
              * @dev Initialize AppProxyUpgradeable (makes it an upgradeable Aragon app)
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload)
                  AppProxyBase(_kernel, _appId, _initializePayload)
                  public // solium-disable-line visibility-first
              {
                  // solium-disable-previous-line no-empty-blocks
              }
          
              /**
               * @dev ERC897, the address the proxy would delegate calls to
               */
              function implementation() public view returns (address) {
                  return getAppBase(appId());
              }
          
              /**
               * @dev ERC897, whether it is a forwarding (1) or an upgradeable (2) proxy
               */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                  return UPGRADEABLE;
              }
          }

          File 3 of 5: KernelProxy
          /**
           *Submitted for verification at Etherscan.io on 2020-02-06
          */
          
          // File: contracts/acl/IACL.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IACL {
              function initialize(address permissionsCreator) external;
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          }
          
          // File: contracts/common/IVaultRecoverable.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IVaultRecoverable {
              event RecoverToVault(address indexed vault, address indexed token, uint256 amount);
          
              function transferToVault(address token) external;
          
              function allowRecoverability(address token) external view returns (bool);
              function getRecoveryVault() external view returns (address);
          }
          
          // File: contracts/kernel/IKernel.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          interface IKernelEvents {
              event SetApp(bytes32 indexed namespace, bytes32 indexed appId, address app);
          }
          
          
          // This should be an interface, but interfaces can't inherit yet :(
          contract IKernel is IKernelEvents, IVaultRecoverable {
              function acl() public view returns (IACL);
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          
              function setApp(bytes32 namespace, bytes32 appId, address app) public;
              function getApp(bytes32 namespace, bytes32 appId) public view returns (address);
          }
          
          // File: contracts/kernel/KernelConstants.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract KernelAppIds {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_APP_ID = apmNamehash("kernel");
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = apmNamehash("acl");
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = apmNamehash("vault");
              */
              bytes32 internal constant KERNEL_CORE_APP_ID = 0x3b4bf6bf3ad5000ecf0f989d5befde585c6860fea3e574a4fab4c49d1c177d9c;
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = 0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a;
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = 0x7e852e0fcfce6551c13800f1e7476f982525c2b5277ba14b24339c68416336d1;
          }
          
          
          contract KernelNamespaceConstants {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_NAMESPACE = keccak256("core");
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = keccak256("base");
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = keccak256("app");
              */
              bytes32 internal constant KERNEL_CORE_NAMESPACE = 0xc681a85306374a5ab27f0bbc385296a54bcd314a1948b6cf61c4ea1bc44bb9f8;
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = 0xf1f3eb40f5bc1ad1344716ced8b8a0431d840b5783aea1fd01786bc26f35ac0f;
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
          }
          
          // File: contracts/kernel/KernelStorage.sol
          
          pragma solidity 0.4.24;
          
          
          contract KernelStorage {
              // namespace => app id => address
              mapping (bytes32 => mapping (bytes32 => address)) public apps;
              bytes32 public recoveryVaultAppId;
          }
          
          // File: contracts/acl/ACLSyntaxSugar.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract ACLSyntaxSugar {
              function arr() internal pure returns (uint256[]) {
                  return new uint256[](0);
              }
          
              function arr(bytes32 _a) internal pure returns (uint256[] r) {
                  return arr(uint256(_a));
              }
          
              function arr(bytes32 _a, bytes32 _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a) internal pure returns (uint256[] r) {
                  return arr(uint256(_a));
              }
          
              function arr(address _a, address _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), _b, _c);
              }
          
              function arr(address _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), _b, _c, _d);
              }
          
              function arr(address _a, uint256 _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a, address _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), _c, _d, _e);
              }
          
              function arr(address _a, address _b, address _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), uint256(_c));
              }
          
              function arr(address _a, address _b, uint256 _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), uint256(_c));
              }
          
              function arr(uint256 _a) internal pure returns (uint256[] r) {
                  r = new uint256[](1);
                  r[0] = _a;
              }
          
              function arr(uint256 _a, uint256 _b) internal pure returns (uint256[] r) {
                  r = new uint256[](2);
                  r[0] = _a;
                  r[1] = _b;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
                  r = new uint256[](3);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
                  r = new uint256[](4);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
                  r[3] = _d;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
                  r = new uint256[](5);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
                  r[3] = _d;
                  r[4] = _e;
              }
          }
          
          
          contract ACLHelpers {
              function decodeParamOp(uint256 _x) internal pure returns (uint8 b) {
                  return uint8(_x >> (8 * 30));
              }
          
              function decodeParamId(uint256 _x) internal pure returns (uint8 b) {
                  return uint8(_x >> (8 * 31));
              }
          
              function decodeParamsList(uint256 _x) internal pure returns (uint32 a, uint32 b, uint32 c) {
                  a = uint32(_x);
                  b = uint32(_x >> (8 * 4));
                  c = uint32(_x >> (8 * 8));
              }
          }
          
          // File: contracts/common/ConversionHelpers.sol
          
          pragma solidity ^0.4.24;
          
          
          library ConversionHelpers {
              string private constant ERROR_IMPROPER_LENGTH = "CONVERSION_IMPROPER_LENGTH";
          
              function dangerouslyCastUintArrayToBytes(uint256[] memory _input) internal pure returns (bytes memory output) {
                  // Force cast the uint256[] into a bytes array, by overwriting its length
                  // Note that the bytes array doesn't need to be initialized as we immediately overwrite it
                  // with the input and a new length. The input becomes invalid from this point forward.
                  uint256 byteLength = _input.length * 32;
                  assembly {
                      output := _input
                      mstore(output, byteLength)
                  }
              }
          
              function dangerouslyCastBytesToUintArray(bytes memory _input) internal pure returns (uint256[] memory output) {
                  // Force cast the bytes array into a uint256[], by overwriting its length
                  // Note that the uint256[] doesn't need to be initialized as we immediately overwrite it
                  // with the input and a new length. The input becomes invalid from this point forward.
                  uint256 intsLength = _input.length / 32;
                  require(_input.length == intsLength * 32, ERROR_IMPROPER_LENGTH);
          
                  assembly {
                      output := _input
                      mstore(output, intsLength)
                  }
              }
          }
          
          // File: contracts/common/IsContract.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract IsContract {
              /*
              * NOTE: this should NEVER be used for authentication
              * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize).
              *
              * This is only intended to be used as a sanity check that an address is actually a contract,
              * RATHER THAN an address not being a contract.
              */
              function isContract(address _target) internal view returns (bool) {
                  if (_target == address(0)) {
                      return false;
                  }
          
                  uint256 size;
                  assembly { size := extcodesize(_target) }
                  return size > 0;
              }
          }
          
          // File: contracts/common/Uint256Helpers.sol
          
          pragma solidity ^0.4.24;
          
          
          library Uint256Helpers {
              uint256 private constant MAX_UINT64 = uint64(-1);
          
              string private constant ERROR_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG";
          
              function toUint64(uint256 a) internal pure returns (uint64) {
                  require(a <= MAX_UINT64, ERROR_NUMBER_TOO_BIG);
                  return uint64(a);
              }
          }
          
          // File: contracts/common/TimeHelpers.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract TimeHelpers {
              using Uint256Helpers for uint256;
          
              /**
              * @dev Returns the current block number.
              *      Using a function rather than `block.number` allows us to easily mock the block number in
              *      tests.
              */
              function getBlockNumber() internal view returns (uint256) {
                  return block.number;
              }
          
              /**
              * @dev Returns the current block number, converted to uint64.
              *      Using a function rather than `block.number` allows us to easily mock the block number in
              *      tests.
              */
              function getBlockNumber64() internal view returns (uint64) {
                  return getBlockNumber().toUint64();
              }
          
              /**
              * @dev Returns the current timestamp.
              *      Using a function rather than `block.timestamp` allows us to easily mock it in
              *      tests.
              */
              function getTimestamp() internal view returns (uint256) {
                  return block.timestamp; // solium-disable-line security/no-block-members
              }
          
              /**
              * @dev Returns the current timestamp, converted to uint64.
              *      Using a function rather than `block.timestamp` allows us to easily mock it in
              *      tests.
              */
              function getTimestamp64() internal view returns (uint64) {
                  return getTimestamp().toUint64();
              }
          }
          
          // File: contracts/common/UnstructuredStorage.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          library UnstructuredStorage {
              function getStorageBool(bytes32 position) internal view returns (bool data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageAddress(bytes32 position) internal view returns (address data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageUint256(bytes32 position) internal view returns (uint256 data) {
                  assembly { data := sload(position) }
              }
          
              function setStorageBool(bytes32 position, bool data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageAddress(bytes32 position, address data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageBytes32(bytes32 position, bytes32 data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageUint256(bytes32 position, uint256 data) internal {
                  assembly { sstore(position, data) }
              }
          }
          
          // File: contracts/common/Initializable.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract Initializable is TimeHelpers {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.initializable.initializationBlock")
              bytes32 internal constant INITIALIZATION_BLOCK_POSITION = 0xebb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e;
          
              string private constant ERROR_ALREADY_INITIALIZED = "INIT_ALREADY_INITIALIZED";
              string private constant ERROR_NOT_INITIALIZED = "INIT_NOT_INITIALIZED";
          
              modifier onlyInit {
                  require(getInitializationBlock() == 0, ERROR_ALREADY_INITIALIZED);
                  _;
              }
          
              modifier isInitialized {
                  require(hasInitialized(), ERROR_NOT_INITIALIZED);
                  _;
              }
          
              /**
              * @return Block number in which the contract was initialized
              */
              function getInitializationBlock() public view returns (uint256) {
                  return INITIALIZATION_BLOCK_POSITION.getStorageUint256();
              }
          
              /**
              * @return Whether the contract has been initialized by the time of the current block
              */
              function hasInitialized() public view returns (bool) {
                  uint256 initializationBlock = getInitializationBlock();
                  return initializationBlock != 0 && getBlockNumber() >= initializationBlock;
              }
          
              /**
              * @dev Function to be called by top level contract after initialization has finished.
              */
              function initialized() internal onlyInit {
                  INITIALIZATION_BLOCK_POSITION.setStorageUint256(getBlockNumber());
              }
          
              /**
              * @dev Function to be called by top level contract after initialization to enable the contract
              *      at a future block number rather than immediately.
              */
              function initializedAt(uint256 _blockNumber) internal onlyInit {
                  INITIALIZATION_BLOCK_POSITION.setStorageUint256(_blockNumber);
              }
          }
          
          // File: contracts/common/Petrifiable.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract Petrifiable is Initializable {
              // Use block UINT256_MAX (which should be never) as the initializable date
              uint256 internal constant PETRIFIED_BLOCK = uint256(-1);
          
              function isPetrified() public view returns (bool) {
                  return getInitializationBlock() == PETRIFIED_BLOCK;
              }
          
              /**
              * @dev Function to be called by top level contract to prevent being initialized.
              *      Useful for freezing base contracts when they're used behind proxies.
              */
              function petrify() internal onlyInit {
                  initializedAt(PETRIFIED_BLOCK);
              }
          }
          
          // File: contracts/lib/token/ERC20.sol
          
          // See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/a9f910d34f0ab33a1ae5e714f69f9596a02b4d91/contracts/token/ERC20/ERC20.sol
          
          pragma solidity ^0.4.24;
          
          
          /**
           * @title ERC20 interface
           * @dev see https://github.com/ethereum/EIPs/issues/20
           */
          contract ERC20 {
              function totalSupply() public view returns (uint256);
          
              function balanceOf(address _who) public view returns (uint256);
          
              function allowance(address _owner, address _spender)
                  public view returns (uint256);
          
              function transfer(address _to, uint256 _value) public returns (bool);
          
              function approve(address _spender, uint256 _value)
                  public returns (bool);
          
              function transferFrom(address _from, address _to, uint256 _value)
                  public returns (bool);
          
              event Transfer(
                  address indexed from,
                  address indexed to,
                  uint256 value
              );
          
              event Approval(
                  address indexed owner,
                  address indexed spender,
                  uint256 value
              );
          }
          
          // File: contracts/common/EtherTokenConstant.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          // aragonOS and aragon-apps rely on address(0) to denote native ETH, in
          // contracts where both tokens and ETH are accepted
          contract EtherTokenConstant {
              address internal constant ETH = address(0);
          }
          
          // File: contracts/common/SafeERC20.sol
          
          // Inspired by AdEx (https://github.com/AdExNetwork/adex-protocol-eth/blob/b9df617829661a7518ee10f4cb6c4108659dd6d5/contracts/libs/SafeERC20.sol)
          // and 0x (https://github.com/0xProject/0x-monorepo/blob/737d1dc54d72872e24abce5a1dbe1b66d35fa21a/contracts/protocol/contracts/protocol/AssetProxy/ERC20Proxy.sol#L143)
          
          pragma solidity ^0.4.24;
          
          
          
          library SafeERC20 {
              // Before 0.5, solidity has a mismatch between `address.transfer()` and `token.transfer()`:
              // https://github.com/ethereum/solidity/issues/3544
              bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb;
          
              string private constant ERROR_TOKEN_BALANCE_REVERTED = "SAFE_ERC_20_BALANCE_REVERTED";
              string private constant ERROR_TOKEN_ALLOWANCE_REVERTED = "SAFE_ERC_20_ALLOWANCE_REVERTED";
          
              function invokeAndCheckSuccess(address _addr, bytes memory _calldata)
                  private
                  returns (bool)
              {
                  bool ret;
                  assembly {
                      let ptr := mload(0x40)    // free memory pointer
          
                      let success := call(
                          gas,                  // forward all gas
                          _addr,                // address
                          0,                    // no value
                          add(_calldata, 0x20), // calldata start
                          mload(_calldata),     // calldata length
                          ptr,                  // write output over free memory
                          0x20                  // uint256 return
                      )
          
                      if gt(success, 0) {
                          // Check number of bytes returned from last function call
                          switch returndatasize
          
                          // No bytes returned: assume success
                          case 0 {
                              ret := 1
                          }
          
                          // 32 bytes returned: check if non-zero
                          case 0x20 {
                              // Only return success if returned data was true
                              // Already have output in ptr
                              ret := eq(mload(ptr), 1)
                          }
          
                          // Not sure what was returned: don't mark as success
                          default { }
                      }
                  }
                  return ret;
              }
          
              function staticInvoke(address _addr, bytes memory _calldata)
                  private
                  view
                  returns (bool, uint256)
              {
                  bool success;
                  uint256 ret;
                  assembly {
                      let ptr := mload(0x40)    // free memory pointer
          
                      success := staticcall(
                          gas,                  // forward all gas
                          _addr,                // address
                          add(_calldata, 0x20), // calldata start
                          mload(_calldata),     // calldata length
                          ptr,                  // write output over free memory
                          0x20                  // uint256 return
                      )
          
                      if gt(success, 0) {
                          ret := mload(ptr)
                      }
                  }
                  return (success, ret);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) {
                  bytes memory transferCallData = abi.encodeWithSelector(
                      TRANSFER_SELECTOR,
                      _to,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, transferCallData);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) {
                  bytes memory transferFromCallData = abi.encodeWithSelector(
                      _token.transferFrom.selector,
                      _from,
                      _to,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, transferFromCallData);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) {
                  bytes memory approveCallData = abi.encodeWithSelector(
                      _token.approve.selector,
                      _spender,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, approveCallData);
              }
          
              /**
              * @dev Static call into ERC20.balanceOf().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticBalanceOf(ERC20 _token, address _owner) internal view returns (uint256) {
                  bytes memory balanceOfCallData = abi.encodeWithSelector(
                      _token.balanceOf.selector,
                      _owner
                  );
          
                  (bool success, uint256 tokenBalance) = staticInvoke(_token, balanceOfCallData);
                  require(success, ERROR_TOKEN_BALANCE_REVERTED);
          
                  return tokenBalance;
              }
          
              /**
              * @dev Static call into ERC20.allowance().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticAllowance(ERC20 _token, address _owner, address _spender) internal view returns (uint256) {
                  bytes memory allowanceCallData = abi.encodeWithSelector(
                      _token.allowance.selector,
                      _owner,
                      _spender
                  );
          
                  (bool success, uint256 allowance) = staticInvoke(_token, allowanceCallData);
                  require(success, ERROR_TOKEN_ALLOWANCE_REVERTED);
          
                  return allowance;
              }
          
              /**
              * @dev Static call into ERC20.totalSupply().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticTotalSupply(ERC20 _token) internal view returns (uint256) {
                  bytes memory totalSupplyCallData = abi.encodeWithSelector(_token.totalSupply.selector);
          
                  (bool success, uint256 totalSupply) = staticInvoke(_token, totalSupplyCallData);
                  require(success, ERROR_TOKEN_ALLOWANCE_REVERTED);
          
                  return totalSupply;
              }
          }
          
          // File: contracts/common/VaultRecoverable.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          
          
          
          contract VaultRecoverable is IVaultRecoverable, EtherTokenConstant, IsContract {
              using SafeERC20 for ERC20;
          
              string private constant ERROR_DISALLOWED = "RECOVER_DISALLOWED";
              string private constant ERROR_VAULT_NOT_CONTRACT = "RECOVER_VAULT_NOT_CONTRACT";
              string private constant ERROR_TOKEN_TRANSFER_FAILED = "RECOVER_TOKEN_TRANSFER_FAILED";
          
              /**
               * @notice Send funds to recovery Vault. This contract should never receive funds,
               *         but in case it does, this function allows one to recover them.
               * @param _token Token balance to be sent to recovery vault.
               */
              function transferToVault(address _token) external {
                  require(allowRecoverability(_token), ERROR_DISALLOWED);
                  address vault = getRecoveryVault();
                  require(isContract(vault), ERROR_VAULT_NOT_CONTRACT);
          
                  uint256 balance;
                  if (_token == ETH) {
                      balance = address(this).balance;
                      vault.transfer(balance);
                  } else {
                      ERC20 token = ERC20(_token);
                      balance = token.staticBalanceOf(this);
                      require(token.safeTransfer(vault, balance), ERROR_TOKEN_TRANSFER_FAILED);
                  }
          
                  emit RecoverToVault(vault, _token, balance);
              }
          
              /**
              * @dev By default deriving from AragonApp makes it recoverable
              * @param token Token address that would be recovered
              * @return bool whether the app allows the recovery
              */
              function allowRecoverability(address token) public view returns (bool) {
                  return true;
              }
          
              // Cast non-implemented interface to be public so we can use it internally
              function getRecoveryVault() public view returns (address);
          }
          
          // File: contracts/apps/AppStorage.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract AppStorage {
              using UnstructuredStorage for bytes32;
          
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_POSITION = keccak256("aragonOS.appStorage.kernel");
              bytes32 internal constant APP_ID_POSITION = keccak256("aragonOS.appStorage.appId");
              */
              bytes32 internal constant KERNEL_POSITION = 0x4172f0f7d2289153072b0a6ca36959e0cbe2efc3afe50fc81636caa96338137b;
              bytes32 internal constant APP_ID_POSITION = 0xd625496217aa6a3453eecb9c3489dc5a53e6c67b444329ea2b2cbc9ff547639b;
          
              function kernel() public view returns (IKernel) {
                  return IKernel(KERNEL_POSITION.getStorageAddress());
              }
          
              function appId() public view returns (bytes32) {
                  return APP_ID_POSITION.getStorageBytes32();
              }
          
              function setKernel(IKernel _kernel) internal {
                  KERNEL_POSITION.setStorageAddress(address(_kernel));
              }
          
              function setAppId(bytes32 _appId) internal {
                  APP_ID_POSITION.setStorageBytes32(_appId);
              }
          }
          
          // File: contracts/lib/misc/ERCProxy.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract ERCProxy {
              uint256 internal constant FORWARDING = 1;
              uint256 internal constant UPGRADEABLE = 2;
          
              function proxyType() public pure returns (uint256 proxyTypeId);
              function implementation() public view returns (address codeAddr);
          }
          
          // File: contracts/common/DelegateProxy.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract DelegateProxy is ERCProxy, IsContract {
              uint256 internal constant FWD_GAS_LIMIT = 10000;
          
              /**
              * @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!)
              * @param _dst Destination address to perform the delegatecall
              * @param _calldata Calldata for the delegatecall
              */
              function delegatedFwd(address _dst, bytes _calldata) internal {
                  require(isContract(_dst));
                  uint256 fwdGasLimit = FWD_GAS_LIMIT;
          
                  assembly {
                      let result := delegatecall(sub(gas, fwdGasLimit), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0)
                      let size := returndatasize
                      let ptr := mload(0x40)
                      returndatacopy(ptr, 0, size)
          
                      // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas.
                      // if the call returned error data, forward it
                      switch result case 0 { revert(ptr, size) }
                      default { return(ptr, size) }
                  }
              }
          }
          
          // File: contracts/common/DepositableStorage.sol
          
          pragma solidity 0.4.24;
          
          
          
          contract DepositableStorage {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.depositableStorage.depositable")
              bytes32 internal constant DEPOSITABLE_POSITION = 0x665fd576fbbe6f247aff98f5c94a561e3f71ec2d3c988d56f12d342396c50cea;
          
              function isDepositable() public view returns (bool) {
                  return DEPOSITABLE_POSITION.getStorageBool();
              }
          
              function setDepositable(bool _depositable) internal {
                  DEPOSITABLE_POSITION.setStorageBool(_depositable);
              }
          }
          
          // File: contracts/common/DepositableDelegateProxy.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract DepositableDelegateProxy is DepositableStorage, DelegateProxy {
              event ProxyDeposit(address sender, uint256 value);
          
              function () external payable {
                  uint256 forwardGasThreshold = FWD_GAS_LIMIT;
                  bytes32 isDepositablePosition = DEPOSITABLE_POSITION;
          
                  // Optimized assembly implementation to prevent EIP-1884 from breaking deposits, reference code in Solidity:
                  // https://github.com/aragon/aragonOS/blob/v4.2.1/contracts/common/DepositableDelegateProxy.sol#L10-L20
                  assembly {
                      // Continue only if the gas left is lower than the threshold for forwarding to the implementation code,
                      // otherwise continue outside of the assembly block.
                      if lt(gas, forwardGasThreshold) {
                          // Only accept the deposit and emit an event if all of the following are true:
                          // the proxy accepts deposits (isDepositable), msg.data.length == 0, and msg.value > 0
                          if and(and(sload(isDepositablePosition), iszero(calldatasize)), gt(callvalue, 0)) {
                              // Equivalent Solidity code for emitting the event:
                              // emit ProxyDeposit(msg.sender, msg.value);
          
                              let logData := mload(0x40) // free memory pointer
                              mstore(logData, caller) // add 'msg.sender' to the log data (first event param)
                              mstore(add(logData, 0x20), callvalue) // add 'msg.value' to the log data (second event param)
          
                              // Emit an event with one topic to identify the event: keccak256('ProxyDeposit(address,uint256)') = 0x15ee...dee1
                              log1(logData, 0x40, 0x15eeaa57c7bd188c1388020bcadc2c436ec60d647d36ef5b9eb3c742217ddee1)
          
                              stop() // Stop. Exits execution context
                          }
          
                          // If any of above checks failed, revert the execution (if ETH was sent, it is returned to the sender)
                          revert(0, 0)
                      }
                  }
          
                  address target = implementation();
                  delegatedFwd(target, msg.data);
              }
          }
          
          // File: contracts/apps/AppProxyBase.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          contract AppProxyBase is AppStorage, DepositableDelegateProxy, KernelNamespaceConstants {
              /**
              * @dev Initialize AppProxy
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload) public {
                  setKernel(_kernel);
                  setAppId(_appId);
          
                  // Implicit check that kernel is actually a Kernel
                  // The EVM doesn't actually provide a way for us to make sure, but we can force a revert to
                  // occur if the kernel is set to 0x0 or a non-code address when we try to call a method on
                  // it.
                  address appCode = getAppBase(_appId);
          
                  // If initialize payload is provided, it will be executed
                  if (_initializePayload.length > 0) {
                      require(isContract(appCode));
                      // Cannot make delegatecall as a delegateproxy.delegatedFwd as it
                      // returns ending execution context and halts contract deployment
                      require(appCode.delegatecall(_initializePayload));
                  }
              }
          
              function getAppBase(bytes32 _appId) internal view returns (address) {
                  return kernel().getApp(KERNEL_APP_BASES_NAMESPACE, _appId);
              }
          }
          
          // File: contracts/apps/AppProxyUpgradeable.sol
          
          pragma solidity 0.4.24;
          
          
          
          contract AppProxyUpgradeable is AppProxyBase {
              /**
              * @dev Initialize AppProxyUpgradeable (makes it an upgradeable Aragon app)
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload)
                  AppProxyBase(_kernel, _appId, _initializePayload)
                  public // solium-disable-line visibility-first
              {
                  // solium-disable-previous-line no-empty-blocks
              }
          
              /**
               * @dev ERC897, the address the proxy would delegate calls to
               */
              function implementation() public view returns (address) {
                  return getAppBase(appId());
              }
          
              /**
               * @dev ERC897, whether it is a forwarding (1) or an upgradeable (2) proxy
               */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                  return UPGRADEABLE;
              }
          }
          
          // File: contracts/apps/AppProxyPinned.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          contract AppProxyPinned is IsContract, AppProxyBase {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.appStorage.pinnedCode")
              bytes32 internal constant PINNED_CODE_POSITION = 0xdee64df20d65e53d7f51cb6ab6d921a0a6a638a91e942e1d8d02df28e31c038e;
          
              /**
              * @dev Initialize AppProxyPinned (makes it an un-upgradeable Aragon app)
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload)
                  AppProxyBase(_kernel, _appId, _initializePayload)
                  public // solium-disable-line visibility-first
              {
                  setPinnedCode(getAppBase(_appId));
                  require(isContract(pinnedCode()));
              }
          
              /**
               * @dev ERC897, the address the proxy would delegate calls to
               */
              function implementation() public view returns (address) {
                  return pinnedCode();
              }
          
              /**
               * @dev ERC897, whether it is a forwarding (1) or an upgradeable (2) proxy
               */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                  return FORWARDING;
              }
          
              function setPinnedCode(address _pinnedCode) internal {
                  PINNED_CODE_POSITION.setStorageAddress(_pinnedCode);
              }
          
              function pinnedCode() internal view returns (address) {
                  return PINNED_CODE_POSITION.getStorageAddress();
              }
          }
          
          // File: contracts/factory/AppProxyFactory.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract AppProxyFactory {
              event NewAppProxy(address proxy, bool isUpgradeable, bytes32 appId);
          
              /**
              * @notice Create a new upgradeable app instance on `_kernel` with identifier `_appId`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @return AppProxyUpgradeable
              */
              function newAppProxy(IKernel _kernel, bytes32 _appId) public returns (AppProxyUpgradeable) {
                  return newAppProxy(_kernel, _appId, new bytes(0));
              }
          
              /**
              * @notice Create a new upgradeable app instance on `_kernel` with identifier `_appId` and initialization payload `_initializePayload`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @return AppProxyUpgradeable
              */
              function newAppProxy(IKernel _kernel, bytes32 _appId, bytes _initializePayload) public returns (AppProxyUpgradeable) {
                  AppProxyUpgradeable proxy = new AppProxyUpgradeable(_kernel, _appId, _initializePayload);
                  emit NewAppProxy(address(proxy), true, _appId);
                  return proxy;
              }
          
              /**
              * @notice Create a new pinned app instance on `_kernel` with identifier `_appId`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @return AppProxyPinned
              */
              function newAppProxyPinned(IKernel _kernel, bytes32 _appId) public returns (AppProxyPinned) {
                  return newAppProxyPinned(_kernel, _appId, new bytes(0));
              }
          
              /**
              * @notice Create a new pinned app instance on `_kernel` with identifier `_appId` and initialization payload `_initializePayload`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @param _initializePayload Proxy initialization payload
              * @return AppProxyPinned
              */
              function newAppProxyPinned(IKernel _kernel, bytes32 _appId, bytes _initializePayload) public returns (AppProxyPinned) {
                  AppProxyPinned proxy = new AppProxyPinned(_kernel, _appId, _initializePayload);
                  emit NewAppProxy(address(proxy), false, _appId);
                  return proxy;
              }
          }
          
          // File: contracts/kernel/Kernel.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          
          
          
          
          
          
          
          // solium-disable-next-line max-len
          contract Kernel is IKernel, KernelStorage, KernelAppIds, KernelNamespaceConstants, Petrifiable, IsContract, VaultRecoverable, AppProxyFactory, ACLSyntaxSugar {
              /* Hardcoded constants to save gas
              bytes32 public constant APP_MANAGER_ROLE = keccak256("APP_MANAGER_ROLE");
              */
              bytes32 public constant APP_MANAGER_ROLE = 0xb6d92708f3d4817afc106147d969e229ced5c46e65e0a5002a0d391287762bd0;
          
              string private constant ERROR_APP_NOT_CONTRACT = "KERNEL_APP_NOT_CONTRACT";
              string private constant ERROR_INVALID_APP_CHANGE = "KERNEL_INVALID_APP_CHANGE";
              string private constant ERROR_AUTH_FAILED = "KERNEL_AUTH_FAILED";
          
              /**
              * @dev Constructor that allows the deployer to choose if the base instance should be petrified immediately.
              * @param _shouldPetrify Immediately petrify this instance so that it can never be initialized
              */
              constructor(bool _shouldPetrify) public {
                  if (_shouldPetrify) {
                      petrify();
                  }
              }
          
              /**
              * @dev Initialize can only be called once. It saves the block number in which it was initialized.
              * @notice Initialize this kernel instance along with its ACL and set `_permissionsCreator` as the entity that can create other permissions
              * @param _baseAcl Address of base ACL app
              * @param _permissionsCreator Entity that will be given permission over createPermission
              */
              function initialize(IACL _baseAcl, address _permissionsCreator) public onlyInit {
                  initialized();
          
                  // Set ACL base
                  _setApp(KERNEL_APP_BASES_NAMESPACE, KERNEL_DEFAULT_ACL_APP_ID, _baseAcl);
          
                  // Create ACL instance and attach it as the default ACL app
                  IACL acl = IACL(newAppProxy(this, KERNEL_DEFAULT_ACL_APP_ID));
                  acl.initialize(_permissionsCreator);
                  _setApp(KERNEL_APP_ADDR_NAMESPACE, KERNEL_DEFAULT_ACL_APP_ID, acl);
          
                  recoveryVaultAppId = KERNEL_DEFAULT_VAULT_APP_ID;
              }
          
              /**
              * @dev Create a new instance of an app linked to this kernel
              * @notice Create a new upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @return AppProxy instance
              */
              function newAppInstance(bytes32 _appId, address _appBase)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  return newAppInstance(_appId, _appBase, new bytes(0), false);
              }
          
              /**
              * @dev Create a new instance of an app linked to this kernel and set its base
              *      implementation if it was not already set
              * @notice Create a new upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`. `_setDefault ? 'Also sets it as the default app instance.':''`
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @param _initializePayload Payload for call made by the proxy during its construction to initialize
              * @param _setDefault Whether the app proxy app is the default one.
              *        Useful when the Kernel needs to know of an instance of a particular app,
              *        like Vault for escape hatch mechanism.
              * @return AppProxy instance
              */
              function newAppInstance(bytes32 _appId, address _appBase, bytes _initializePayload, bool _setDefault)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  _setAppIfNew(KERNEL_APP_BASES_NAMESPACE, _appId, _appBase);
                  appProxy = newAppProxy(this, _appId, _initializePayload);
                  // By calling setApp directly and not the internal functions, we make sure the params are checked
                  // and it will only succeed if sender has permissions to set something to the namespace.
                  if (_setDefault) {
                      setApp(KERNEL_APP_ADDR_NAMESPACE, _appId, appProxy);
                  }
              }
          
              /**
              * @dev Create a new pinned instance of an app linked to this kernel
              * @notice Create a new non-upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`.
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @return AppProxy instance
              */
              function newPinnedAppInstance(bytes32 _appId, address _appBase)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  return newPinnedAppInstance(_appId, _appBase, new bytes(0), false);
              }
          
              /**
              * @dev Create a new pinned instance of an app linked to this kernel and set
              *      its base implementation if it was not already set
              * @notice Create a new non-upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`. `_setDefault ? 'Also sets it as the default app instance.':''`
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @param _initializePayload Payload for call made by the proxy during its construction to initialize
              * @param _setDefault Whether the app proxy app is the default one.
              *        Useful when the Kernel needs to know of an instance of a particular app,
              *        like Vault for escape hatch mechanism.
              * @return AppProxy instance
              */
              function newPinnedAppInstance(bytes32 _appId, address _appBase, bytes _initializePayload, bool _setDefault)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  _setAppIfNew(KERNEL_APP_BASES_NAMESPACE, _appId, _appBase);
                  appProxy = newAppProxyPinned(this, _appId, _initializePayload);
                  // By calling setApp directly and not the internal functions, we make sure the params are checked
                  // and it will only succeed if sender has permissions to set something to the namespace.
                  if (_setDefault) {
                      setApp(KERNEL_APP_ADDR_NAMESPACE, _appId, appProxy);
                  }
              }
          
              /**
              * @dev Set the resolving address of an app instance or base implementation
              * @notice Set the resolving address of `_appId` in namespace `_namespace` to `_app`
              * @param _namespace App namespace to use
              * @param _appId Identifier for app
              * @param _app Address of the app instance or base implementation
              * @return ID of app
              */
              function setApp(bytes32 _namespace, bytes32 _appId, address _app)
                  public
                  auth(APP_MANAGER_ROLE, arr(_namespace, _appId))
              {
                  _setApp(_namespace, _appId, _app);
              }
          
              /**
              * @dev Set the default vault id for the escape hatch mechanism
              * @param _recoveryVaultAppId Identifier of the recovery vault app
              */
              function setRecoveryVaultAppId(bytes32 _recoveryVaultAppId)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_ADDR_NAMESPACE, _recoveryVaultAppId))
              {
                  recoveryVaultAppId = _recoveryVaultAppId;
              }
          
              // External access to default app id and namespace constants to mimic default getters for constants
              /* solium-disable function-order, mixedcase */
              function CORE_NAMESPACE() external pure returns (bytes32) { return KERNEL_CORE_NAMESPACE; }
              function APP_BASES_NAMESPACE() external pure returns (bytes32) { return KERNEL_APP_BASES_NAMESPACE; }
              function APP_ADDR_NAMESPACE() external pure returns (bytes32) { return KERNEL_APP_ADDR_NAMESPACE; }
              function KERNEL_APP_ID() external pure returns (bytes32) { return KERNEL_CORE_APP_ID; }
              function DEFAULT_ACL_APP_ID() external pure returns (bytes32) { return KERNEL_DEFAULT_ACL_APP_ID; }
              /* solium-enable function-order, mixedcase */
          
              /**
              * @dev Get the address of an app instance or base implementation
              * @param _namespace App namespace to use
              * @param _appId Identifier for app
              * @return Address of the app
              */
              function getApp(bytes32 _namespace, bytes32 _appId) public view returns (address) {
                  return apps[_namespace][_appId];
              }
          
              /**
              * @dev Get the address of the recovery Vault instance (to recover funds)
              * @return Address of the Vault
              */
              function getRecoveryVault() public view returns (address) {
                  return apps[KERNEL_APP_ADDR_NAMESPACE][recoveryVaultAppId];
              }
          
              /**
              * @dev Get the installed ACL app
              * @return ACL app
              */
              function acl() public view returns (IACL) {
                  return IACL(getApp(KERNEL_APP_ADDR_NAMESPACE, KERNEL_DEFAULT_ACL_APP_ID));
              }
          
              /**
              * @dev Function called by apps to check ACL on kernel or to check permission status
              * @param _who Sender of the original call
              * @param _where Address of the app
              * @param _what Identifier for a group of actions in app
              * @param _how Extra data for ACL auth
              * @return Boolean indicating whether the ACL allows the role or not.
              *         Always returns false if the kernel hasn't been initialized yet.
              */
              function hasPermission(address _who, address _where, bytes32 _what, bytes _how) public view returns (bool) {
                  IACL defaultAcl = acl();
                  return address(defaultAcl) != address(0) && // Poor man's initialization check (saves gas)
                      defaultAcl.hasPermission(_who, _where, _what, _how);
              }
          
              function _setApp(bytes32 _namespace, bytes32 _appId, address _app) internal {
                  require(isContract(_app), ERROR_APP_NOT_CONTRACT);
                  apps[_namespace][_appId] = _app;
                  emit SetApp(_namespace, _appId, _app);
              }
          
              function _setAppIfNew(bytes32 _namespace, bytes32 _appId, address _app) internal {
                  address app = getApp(_namespace, _appId);
                  if (app != address(0)) {
                      // The only way to set an app is if it passes the isContract check, so no need to check it again
                      require(app == _app, ERROR_INVALID_APP_CHANGE);
                  } else {
                      _setApp(_namespace, _appId, _app);
                  }
              }
          
              modifier auth(bytes32 _role, uint256[] memory _params) {
                  require(
                      hasPermission(msg.sender, address(this), _role, ConversionHelpers.dangerouslyCastUintArrayToBytes(_params)),
                      ERROR_AUTH_FAILED
                  );
                  _;
              }
          }
          
          // File: contracts/kernel/KernelProxy.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          
          contract KernelProxy is IKernelEvents, KernelStorage, KernelAppIds, KernelNamespaceConstants, IsContract, DepositableDelegateProxy {
              /**
              * @dev KernelProxy is a proxy contract to a kernel implementation. The implementation
              *      can update the reference, which effectively upgrades the contract
              * @param _kernelImpl Address of the contract used as implementation for kernel
              */
              constructor(IKernel _kernelImpl) public {
                  require(isContract(address(_kernelImpl)));
                  apps[KERNEL_CORE_NAMESPACE][KERNEL_CORE_APP_ID] = _kernelImpl;
          
                  // Note that emitting this event is important for verifying that a KernelProxy instance
                  // was never upgraded to a malicious Kernel logic contract over its lifespan.
                  // This starts the "chain of trust", that can be followed through later SetApp() events
                  // emitted during kernel upgrades.
                  emit SetApp(KERNEL_CORE_NAMESPACE, KERNEL_CORE_APP_ID, _kernelImpl);
              }
          
              /**
               * @dev ERC897, whether it is a forwarding (1) or an upgradeable (2) proxy
               */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                  return UPGRADEABLE;
              }
          
              /**
              * @dev ERC897, the address the proxy would delegate calls to
              */
              function implementation() public view returns (address) {
                  return apps[KERNEL_CORE_NAMESPACE][KERNEL_CORE_APP_ID];
              }
          }
          
          // File: contracts/common/Autopetrified.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract Autopetrified is Petrifiable {
              constructor() public {
                  // Immediately petrify base (non-proxy) instances of inherited contracts on deploy.
                  // This renders them uninitializable (and unusable without a proxy).
                  petrify();
              }
          }
          
          // File: contracts/common/ReentrancyGuard.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract ReentrancyGuard {
              using UnstructuredStorage for bytes32;
          
              /* Hardcoded constants to save gas
              bytes32 internal constant REENTRANCY_MUTEX_POSITION = keccak256("aragonOS.reentrancyGuard.mutex");
              */
              bytes32 private constant REENTRANCY_MUTEX_POSITION = 0xe855346402235fdd185c890e68d2c4ecad599b88587635ee285bce2fda58dacb;
          
              string private constant ERROR_REENTRANT = "REENTRANCY_REENTRANT_CALL";
          
              modifier nonReentrant() {
                  // Ensure mutex is unlocked
                  require(!REENTRANCY_MUTEX_POSITION.getStorageBool(), ERROR_REENTRANT);
          
                  // Lock mutex before function call
                  REENTRANCY_MUTEX_POSITION.setStorageBool(true);
          
                  // Perform function call
                  _;
          
                  // Unlock mutex after function call
                  REENTRANCY_MUTEX_POSITION.setStorageBool(false);
              }
          }
          
          // File: contracts/evmscript/IEVMScriptExecutor.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IEVMScriptExecutor {
              function execScript(bytes script, bytes input, address[] blacklist) external returns (bytes);
              function executorType() external pure returns (bytes32);
          }
          
          // File: contracts/evmscript/IEVMScriptRegistry.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract EVMScriptRegistryConstants {
              /* Hardcoded constants to save gas
              bytes32 internal constant EVMSCRIPT_REGISTRY_APP_ID = apmNamehash("evmreg");
              */
              bytes32 internal constant EVMSCRIPT_REGISTRY_APP_ID = 0xddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd61;
          }
          
          
          interface IEVMScriptRegistry {
              function addScriptExecutor(IEVMScriptExecutor executor) external returns (uint id);
              function disableScriptExecutor(uint256 executorId) external;
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function getScriptExecutor(bytes script) public view returns (IEVMScriptExecutor);
          }
          
          // File: contracts/evmscript/EVMScriptRunner.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          
          
          
          contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelNamespaceConstants {
              string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE";
              string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED";
          
              /* This is manually crafted in assembly
              string private constant ERROR_EXECUTOR_INVALID_RETURN = "EVMRUN_EXECUTOR_INVALID_RETURN";
              */
          
              event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData);
          
              function getEVMScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) {
                  return IEVMScriptExecutor(getEVMScriptRegistry().getScriptExecutor(_script));
              }
          
              function getEVMScriptRegistry() public view returns (IEVMScriptRegistry) {
                  address registryAddr = kernel().getApp(KERNEL_APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID);
                  return IEVMScriptRegistry(registryAddr);
              }
          
              function runScript(bytes _script, bytes _input, address[] _blacklist)
                  internal
                  isInitialized
                  protectState
                  returns (bytes)
              {
                  IEVMScriptExecutor executor = getEVMScriptExecutor(_script);
                  require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE);
          
                  bytes4 sig = executor.execScript.selector;
                  bytes memory data = abi.encodeWithSelector(sig, _script, _input, _blacklist);
          
                  bytes memory output;
                  assembly {
                      let success := delegatecall(
                          gas,                // forward all gas
                          executor,           // address
                          add(data, 0x20),    // calldata start
                          mload(data),        // calldata length
                          0,                  // don't write output (we'll handle this ourselves)
                          0                   // don't write output
                      )
          
                      output := mload(0x40) // free mem ptr get
          
                      switch success
                      case 0 {
                          // If the call errored, forward its full error data
                          returndatacopy(output, 0, returndatasize)
                          revert(output, returndatasize)
                      }
                      default {
                          switch gt(returndatasize, 0x3f)
                          case 0 {
                              // Need at least 0x40 bytes returned for properly ABI-encoded bytes values,
                              // revert with "EVMRUN_EXECUTOR_INVALID_RETURN"
                              // See remix: doing a `revert("EVMRUN_EXECUTOR_INVALID_RETURN")` always results in
                              // this memory layout
                              mstore(output, 0x08c379a000000000000000000000000000000000000000000000000000000000)         // error identifier
                              mstore(add(output, 0x04), 0x0000000000000000000000000000000000000000000000000000000000000020) // starting offset
                              mstore(add(output, 0x24), 0x000000000000000000000000000000000000000000000000000000000000001e) // reason length
                              mstore(add(output, 0x44), 0x45564d52554e5f4558454355544f525f494e56414c49445f52455455524e0000) // reason
          
                              revert(output, 100) // 100 = 4 + 3 * 32 (error identifier + 3 words for the ABI encoded error)
                          }
                          default {
                              // Copy result
                              //
                              // Needs to perform an ABI decode for the expected `bytes` return type of
                              // `executor.execScript()` as solidity will automatically ABI encode the returned bytes as:
                              //    [ position of the first dynamic length return value = 0x20 (32 bytes) ]
                              //    [ output length (32 bytes) ]
                              //    [ output content (N bytes) ]
                              //
                              // Perform the ABI decode by ignoring the first 32 bytes of the return data
                              let copysize := sub(returndatasize, 0x20)
                              returndatacopy(output, 0x20, copysize)
          
                              mstore(0x40, add(output, copysize)) // free mem ptr set
                          }
                      }
                  }
          
                  emit ScriptResult(address(executor), _script, _input, output);
          
                  return output;
              }
          
              modifier protectState {
                  address preKernel = address(kernel());
                  bytes32 preAppId = appId();
                  _; // exec
                  require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED);
                  require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED);
              }
          }
          
          // File: contracts/apps/AragonApp.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          
          
          
          
          
          // Contracts inheriting from AragonApp are, by default, immediately petrified upon deployment so
          // that they can never be initialized.
          // Unless overriden, this behaviour enforces those contracts to be usable only behind an AppProxy.
          // ReentrancyGuard, EVMScriptRunner, and ACLSyntaxSugar are not directly used by this contract, but
          // are included so that they are automatically usable by subclassing contracts
          contract AragonApp is AppStorage, Autopetrified, VaultRecoverable, ReentrancyGuard, EVMScriptRunner, ACLSyntaxSugar {
              string private constant ERROR_AUTH_FAILED = "APP_AUTH_FAILED";
          
              modifier auth(bytes32 _role) {
                  require(canPerform(msg.sender, _role, new uint256[](0)), ERROR_AUTH_FAILED);
                  _;
              }
          
              modifier authP(bytes32 _role, uint256[] _params) {
                  require(canPerform(msg.sender, _role, _params), ERROR_AUTH_FAILED);
                  _;
              }
          
              /**
              * @dev Check whether an action can be performed by a sender for a particular role on this app
              * @param _sender Sender of the call
              * @param _role Role on this app
              * @param _params Permission params for the role
              * @return Boolean indicating whether the sender has the permissions to perform the action.
              *         Always returns false if the app hasn't been initialized yet.
              */
              function canPerform(address _sender, bytes32 _role, uint256[] _params) public view returns (bool) {
                  if (!hasInitialized()) {
                      return false;
                  }
          
                  IKernel linkedKernel = kernel();
                  if (address(linkedKernel) == address(0)) {
                      return false;
                  }
          
                  return linkedKernel.hasPermission(
                      _sender,
                      address(this),
                      _role,
                      ConversionHelpers.dangerouslyCastUintArrayToBytes(_params)
                  );
              }
          
              /**
              * @dev Get the recovery vault for the app
              * @return Recovery vault address for the app
              */
              function getRecoveryVault() public view returns (address) {
                  // Funds recovery via a vault is only available when used with a kernel
                  return kernel().getRecoveryVault(); // if kernel is not set, it will revert
              }
          }
          
          // File: contracts/acl/IACLOracle.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IACLOracle {
              function canPerform(address who, address where, bytes32 what, uint256[] how) external view returns (bool);
          }
          
          // File: contracts/acl/ACL.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          
          
          /* solium-disable function-order */
          // Allow public initialize() to be first
          contract ACL is IACL, TimeHelpers, AragonApp, ACLHelpers {
              /* Hardcoded constants to save gas
              bytes32 public constant CREATE_PERMISSIONS_ROLE = keccak256("CREATE_PERMISSIONS_ROLE");
              */
              bytes32 public constant CREATE_PERMISSIONS_ROLE = 0x0b719b33c83b8e5d300c521cb8b54ae9bd933996a14bef8c2f4e0285d2d2400a;
          
              enum Op { NONE, EQ, NEQ, GT, LT, GTE, LTE, RET, NOT, AND, OR, XOR, IF_ELSE } // op types
          
              struct Param {
                  uint8 id;
                  uint8 op;
                  uint240 value; // even though value is an uint240 it can store addresses
                  // in the case of 32 byte hashes losing 2 bytes precision isn't a huge deal
                  // op and id take less than 1 byte each so it can be kept in 1 sstore
              }
          
              uint8 internal constant BLOCK_NUMBER_PARAM_ID = 200;
              uint8 internal constant TIMESTAMP_PARAM_ID    = 201;
              // 202 is unused
              uint8 internal constant ORACLE_PARAM_ID       = 203;
              uint8 internal constant LOGIC_OP_PARAM_ID     = 204;
              uint8 internal constant PARAM_VALUE_PARAM_ID  = 205;
              // TODO: Add execution times param type?
          
              /* Hardcoded constant to save gas
              bytes32 public constant EMPTY_PARAM_HASH = keccak256(uint256(0));
              */
              bytes32 public constant EMPTY_PARAM_HASH = 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563;
              bytes32 public constant NO_PERMISSION = bytes32(0);
              address public constant ANY_ENTITY = address(-1);
              address public constant BURN_ENTITY = address(1); // address(0) is already used as "no permission manager"
          
              string private constant ERROR_AUTH_INIT_KERNEL = "ACL_AUTH_INIT_KERNEL";
              string private constant ERROR_AUTH_NO_MANAGER = "ACL_AUTH_NO_MANAGER";
              string private constant ERROR_EXISTENT_MANAGER = "ACL_EXISTENT_MANAGER";
          
              // Whether someone has a permission
              mapping (bytes32 => bytes32) internal permissions; // permissions hash => params hash
              mapping (bytes32 => Param[]) internal permissionParams; // params hash => params
          
              // Who is the manager of a permission
              mapping (bytes32 => address) internal permissionManager;
          
              event SetPermission(address indexed entity, address indexed app, bytes32 indexed role, bool allowed);
              event SetPermissionParams(address indexed entity, address indexed app, bytes32 indexed role, bytes32 paramsHash);
              event ChangePermissionManager(address indexed app, bytes32 indexed role, address indexed manager);
          
              modifier onlyPermissionManager(address _app, bytes32 _role) {
                  require(msg.sender == getPermissionManager(_app, _role), ERROR_AUTH_NO_MANAGER);
                  _;
              }
          
              modifier noPermissionManager(address _app, bytes32 _role) {
                  // only allow permission creation (or re-creation) when there is no manager
                  require(getPermissionManager(_app, _role) == address(0), ERROR_EXISTENT_MANAGER);
                  _;
              }
          
              /**
              * @dev Initialize can only be called once. It saves the block number in which it was initialized.
              * @notice Initialize an ACL instance and set `_permissionsCreator` as the entity that can create other permissions
              * @param _permissionsCreator Entity that will be given permission over createPermission
              */
              function initialize(address _permissionsCreator) public onlyInit {
                  initialized();
                  require(msg.sender == address(kernel()), ERROR_AUTH_INIT_KERNEL);
          
                  _createPermission(_permissionsCreator, this, CREATE_PERMISSIONS_ROLE, _permissionsCreator);
              }
          
              /**
              * @dev Creates a permission that wasn't previously set and managed.
              *      If a created permission is removed it is possible to reset it with createPermission.
              *      This is the **ONLY** way to create permissions and set managers to permissions that don't
              *      have a manager.
              *      In terms of the ACL being initialized, this function implicitly protects all the other
              *      state-changing external functions, as they all require the sender to be a manager.
              * @notice Create a new permission granting `_entity` the ability to perform actions requiring `_role` on `_app`, setting `_manager` as the permission's manager
              * @param _entity Address of the whitelisted entity that will be able to perform the role
              * @param _app Address of the app in which the role will be allowed (requires app to depend on kernel for ACL)
              * @param _role Identifier for the group of actions in app given access to perform
              * @param _manager Address of the entity that will be able to grant and revoke the permission further.
              */
              function createPermission(address _entity, address _app, bytes32 _role, address _manager)
                  external
                  auth(CREATE_PERMISSIONS_ROLE)
                  noPermissionManager(_app, _role)
              {
                  _createPermission(_entity, _app, _role, _manager);
              }
          
              /**
              * @dev Grants permission if allowed. This requires `msg.sender` to be the permission manager
              * @notice Grant `_entity` the ability to perform actions requiring `_role` on `_app`
              * @param _entity Address of the whitelisted entity that will be able to perform the role
              * @param _app Address of the app in which the role will be allowed (requires app to depend on kernel for ACL)
              * @param _role Identifier for the group of actions in app given access to perform
              */
              function grantPermission(address _entity, address _app, bytes32 _role)
                  external
              {
                  grantPermissionP(_entity, _app, _role, new uint256[](0));
              }
          
              /**
              * @dev Grants a permission with parameters if allowed. This requires `msg.sender` to be the permission manager
              * @notice Grant `_entity` the ability to perform actions requiring `_role` on `_app`
              * @param _entity Address of the whitelisted entity that will be able to perform the role
              * @param _app Address of the app in which the role will be allowed (requires app to depend on kernel for ACL)
              * @param _role Identifier for the group of actions in app given access to perform
              * @param _params Permission parameters
              */
              function grantPermissionP(address _entity, address _app, bytes32 _role, uint256[] _params)
                  public
                  onlyPermissionManager(_app, _role)
              {
                  bytes32 paramsHash = _params.length > 0 ? _saveParams(_params) : EMPTY_PARAM_HASH;
                  _setPermission(_entity, _app, _role, paramsHash);
              }
          
              /**
              * @dev Revokes permission if allowed. This requires `msg.sender` to be the the permission manager
              * @notice Revoke from `_entity` the ability to perform actions requiring `_role` on `_app`
              * @param _entity Address of the whitelisted entity to revoke access from
              * @param _app Address of the app in which the role will be revoked
              * @param _role Identifier for the group of actions in app being revoked
              */
              function revokePermission(address _entity, address _app, bytes32 _role)
                  external
                  onlyPermissionManager(_app, _role)
              {
                  _setPermission(_entity, _app, _role, NO_PERMISSION);
              }
          
              /**
              * @notice Set `_newManager` as the manager of `_role` in `_app`
              * @param _newManager Address for the new manager
              * @param _app Address of the app in which the permission management is being transferred
              * @param _role Identifier for the group of actions being transferred
              */
              function setPermissionManager(address _newManager, address _app, bytes32 _role)
                  external
                  onlyPermissionManager(_app, _role)
              {
                  _setPermissionManager(_newManager, _app, _role);
              }
          
              /**
              * @notice Remove the manager of `_role` in `_app`
              * @param _app Address of the app in which the permission is being unmanaged
              * @param _role Identifier for the group of actions being unmanaged
              */
              function removePermissionManager(address _app, bytes32 _role)
                  external
                  onlyPermissionManager(_app, _role)
              {
                  _setPermissionManager(address(0), _app, _role);
              }
          
              /**
              * @notice Burn non-existent `_role` in `_app`, so no modification can be made to it (grant, revoke, permission manager)
              * @param _app Address of the app in which the permission is being burned
              * @param _role Identifier for the group of actions being burned
              */
              function createBurnedPermission(address _app, bytes32 _role)
                  external
                  auth(CREATE_PERMISSIONS_ROLE)
                  noPermissionManager(_app, _role)
              {
                  _setPermissionManager(BURN_ENTITY, _app, _role);
              }
          
              /**
              * @notice Burn `_role` in `_app`, so no modification can be made to it (grant, revoke, permission manager)
              * @param _app Address of the app in which the permission is being burned
              * @param _role Identifier for the group of actions being burned
              */
              function burnPermissionManager(address _app, bytes32 _role)
                  external
                  onlyPermissionManager(_app, _role)
              {
                  _setPermissionManager(BURN_ENTITY, _app, _role);
              }
          
              /**
               * @notice Get parameters for permission array length
               * @param _entity Address of the whitelisted entity that will be able to perform the role
               * @param _app Address of the app
               * @param _role Identifier for a group of actions in app
               * @return Length of the array
               */
              function getPermissionParamsLength(address _entity, address _app, bytes32 _role) external view returns (uint) {
                  return permissionParams[permissions[permissionHash(_entity, _app, _role)]].length;
              }
          
              /**
              * @notice Get parameter for permission
              * @param _entity Address of the whitelisted entity that will be able to perform the role
              * @param _app Address of the app
              * @param _role Identifier for a group of actions in app
              * @param _index Index of parameter in the array
              * @return Parameter (id, op, value)
              */
              function getPermissionParam(address _entity, address _app, bytes32 _role, uint _index)
                  external
                  view
                  returns (uint8, uint8, uint240)
              {
                  Param storage param = permissionParams[permissions[permissionHash(_entity, _app, _role)]][_index];
                  return (param.id, param.op, param.value);
              }
          
              /**
              * @dev Get manager for permission
              * @param _app Address of the app
              * @param _role Identifier for a group of actions in app
              * @return address of the manager for the permission
              */
              function getPermissionManager(address _app, bytes32 _role) public view returns (address) {
                  return permissionManager[roleHash(_app, _role)];
              }
          
              /**
              * @dev Function called by apps to check ACL on kernel or to check permission statu
              * @param _who Sender of the original call
              * @param _where Address of the app
              * @param _where Identifier for a group of actions in app
              * @param _how Permission parameters
              * @return boolean indicating whether the ACL allows the role or not
              */
              function hasPermission(address _who, address _where, bytes32 _what, bytes memory _how) public view returns (bool) {
                  return hasPermission(_who, _where, _what, ConversionHelpers.dangerouslyCastBytesToUintArray(_how));
              }
          
              function hasPermission(address _who, address _where, bytes32 _what, uint256[] memory _how) public view returns (bool) {
                  bytes32 whoParams = permissions[permissionHash(_who, _where, _what)];
                  if (whoParams != NO_PERMISSION && evalParams(whoParams, _who, _where, _what, _how)) {
                      return true;
                  }
          
                  bytes32 anyParams = permissions[permissionHash(ANY_ENTITY, _where, _what)];
                  if (anyParams != NO_PERMISSION && evalParams(anyParams, ANY_ENTITY, _where, _what, _how)) {
                      return true;
                  }
          
                  return false;
              }
          
              function hasPermission(address _who, address _where, bytes32 _what) public view returns (bool) {
                  uint256[] memory empty = new uint256[](0);
                  return hasPermission(_who, _where, _what, empty);
              }
          
              function evalParams(
                  bytes32 _paramsHash,
                  address _who,
                  address _where,
                  bytes32 _what,
                  uint256[] _how
              ) public view returns (bool)
              {
                  if (_paramsHash == EMPTY_PARAM_HASH) {
                      return true;
                  }
          
                  return _evalParam(_paramsHash, 0, _who, _where, _what, _how);
              }
          
              /**
              * @dev Internal createPermission for access inside the kernel (on instantiation)
              */
              function _createPermission(address _entity, address _app, bytes32 _role, address _manager) internal {
                  _setPermission(_entity, _app, _role, EMPTY_PARAM_HASH);
                  _setPermissionManager(_manager, _app, _role);
              }
          
              /**
              * @dev Internal function called to actually save the permission
              */
              function _setPermission(address _entity, address _app, bytes32 _role, bytes32 _paramsHash) internal {
                  permissions[permissionHash(_entity, _app, _role)] = _paramsHash;
                  bool entityHasPermission = _paramsHash != NO_PERMISSION;
                  bool permissionHasParams = entityHasPermission && _paramsHash != EMPTY_PARAM_HASH;
          
                  emit SetPermission(_entity, _app, _role, entityHasPermission);
                  if (permissionHasParams) {
                      emit SetPermissionParams(_entity, _app, _role, _paramsHash);
                  }
              }
          
              function _saveParams(uint256[] _encodedParams) internal returns (bytes32) {
                  bytes32 paramHash = keccak256(abi.encodePacked(_encodedParams));
                  Param[] storage params = permissionParams[paramHash];
          
                  if (params.length == 0) { // params not saved before
                      for (uint256 i = 0; i < _encodedParams.length; i++) {
                          uint256 encodedParam = _encodedParams[i];
                          Param memory param = Param(decodeParamId(encodedParam), decodeParamOp(encodedParam), uint240(encodedParam));
                          params.push(param);
                      }
                  }
          
                  return paramHash;
              }
          
              function _evalParam(
                  bytes32 _paramsHash,
                  uint32 _paramId,
                  address _who,
                  address _where,
                  bytes32 _what,
                  uint256[] _how
              ) internal view returns (bool)
              {
                  if (_paramId >= permissionParams[_paramsHash].length) {
                      return false; // out of bounds
                  }
          
                  Param memory param = permissionParams[_paramsHash][_paramId];
          
                  if (param.id == LOGIC_OP_PARAM_ID) {
                      return _evalLogic(param, _paramsHash, _who, _where, _what, _how);
                  }
          
                  uint256 value;
                  uint256 comparedTo = uint256(param.value);
          
                  // get value
                  if (param.id == ORACLE_PARAM_ID) {
                      value = checkOracle(IACLOracle(param.value), _who, _where, _what, _how) ? 1 : 0;
                      comparedTo = 1;
                  } else if (param.id == BLOCK_NUMBER_PARAM_ID) {
                      value = getBlockNumber();
                  } else if (param.id == TIMESTAMP_PARAM_ID) {
                      value = getTimestamp();
                  } else if (param.id == PARAM_VALUE_PARAM_ID) {
                      value = uint256(param.value);
                  } else {
                      if (param.id >= _how.length) {
                          return false;
                      }
                      value = uint256(uint240(_how[param.id])); // force lost precision
                  }
          
                  if (Op(param.op) == Op.RET) {
                      return uint256(value) > 0;
                  }
          
                  return compare(value, Op(param.op), comparedTo);
              }
          
              function _evalLogic(Param _param, bytes32 _paramsHash, address _who, address _where, bytes32 _what, uint256[] _how)
                  internal
                  view
                  returns (bool)
              {
                  if (Op(_param.op) == Op.IF_ELSE) {
                      uint32 conditionParam;
                      uint32 successParam;
                      uint32 failureParam;
          
                      (conditionParam, successParam, failureParam) = decodeParamsList(uint256(_param.value));
                      bool result = _evalParam(_paramsHash, conditionParam, _who, _where, _what, _how);
          
                      return _evalParam(_paramsHash, result ? successParam : failureParam, _who, _where, _what, _how);
                  }
          
                  uint32 param1;
                  uint32 param2;
          
                  (param1, param2,) = decodeParamsList(uint256(_param.value));
                  bool r1 = _evalParam(_paramsHash, param1, _who, _where, _what, _how);
          
                  if (Op(_param.op) == Op.NOT) {
                      return !r1;
                  }
          
                  if (r1 && Op(_param.op) == Op.OR) {
                      return true;
                  }
          
                  if (!r1 && Op(_param.op) == Op.AND) {
                      return false;
                  }
          
                  bool r2 = _evalParam(_paramsHash, param2, _who, _where, _what, _how);
          
                  if (Op(_param.op) == Op.XOR) {
                      return r1 != r2;
                  }
          
                  return r2; // both or and and depend on result of r2 after checks
              }
          
              function compare(uint256 _a, Op _op, uint256 _b) internal pure returns (bool) {
                  if (_op == Op.EQ)  return _a == _b;                              // solium-disable-line lbrace
                  if (_op == Op.NEQ) return _a != _b;                              // solium-disable-line lbrace
                  if (_op == Op.GT)  return _a > _b;                               // solium-disable-line lbrace
                  if (_op == Op.LT)  return _a < _b;                               // solium-disable-line lbrace
                  if (_op == Op.GTE) return _a >= _b;                              // solium-disable-line lbrace
                  if (_op == Op.LTE) return _a <= _b;                              // solium-disable-line lbrace
                  return false;
              }
          
              function checkOracle(IACLOracle _oracleAddr, address _who, address _where, bytes32 _what, uint256[] _how) internal view returns (bool) {
                  bytes4 sig = _oracleAddr.canPerform.selector;
          
                  // a raw call is required so we can return false if the call reverts, rather than reverting
                  bytes memory checkCalldata = abi.encodeWithSelector(sig, _who, _where, _what, _how);
          
                  bool ok;
                  assembly {
                      // send all available gas; if the oracle eats up all the gas, we will eventually revert
                      // note that we are currently guaranteed to still have some gas after the call from
                      // EIP-150's 63/64 gas forward rule
                      ok := staticcall(gas, _oracleAddr, add(checkCalldata, 0x20), mload(checkCalldata), 0, 0)
                  }
          
                  if (!ok) {
                      return false;
                  }
          
                  uint256 size;
                  assembly { size := returndatasize }
                  if (size != 32) {
                      return false;
                  }
          
                  bool result;
                  assembly {
                      let ptr := mload(0x40)       // get next free memory ptr
                      returndatacopy(ptr, 0, size) // copy return from above `staticcall`
                      result := mload(ptr)         // read data at ptr and set it to result
                      mstore(ptr, 0)               // set pointer memory to 0 so it still is the next free ptr
                  }
          
                  return result;
              }
          
              /**
              * @dev Internal function that sets management
              */
              function _setPermissionManager(address _newManager, address _app, bytes32 _role) internal {
                  permissionManager[roleHash(_app, _role)] = _newManager;
                  emit ChangePermissionManager(_app, _role, _newManager);
              }
          
              function roleHash(address _where, bytes32 _what) internal pure returns (bytes32) {
                  return keccak256(abi.encodePacked("ROLE", _where, _what));
              }
          
              function permissionHash(address _who, address _where, bytes32 _what) internal pure returns (bytes32) {
                  return keccak256(abi.encodePacked("PERMISSION", _who, _where, _what));
              }
          }
          
          // File: contracts/evmscript/ScriptHelpers.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          library ScriptHelpers {
              function getSpecId(bytes _script) internal pure returns (uint32) {
                  return uint32At(_script, 0);
              }
          
              function uint256At(bytes _data, uint256 _location) internal pure returns (uint256 result) {
                  assembly {
                      result := mload(add(_data, add(0x20, _location)))
                  }
              }
          
              function addressAt(bytes _data, uint256 _location) internal pure returns (address result) {
                  uint256 word = uint256At(_data, _location);
          
                  assembly {
                      result := div(and(word, 0xffffffffffffffffffffffffffffffffffffffff000000000000000000000000),
                      0x1000000000000000000000000)
                  }
              }
          
              function uint32At(bytes _data, uint256 _location) internal pure returns (uint32 result) {
                  uint256 word = uint256At(_data, _location);
          
                  assembly {
                      result := div(and(word, 0xffffffff00000000000000000000000000000000000000000000000000000000),
                      0x100000000000000000000000000000000000000000000000000000000)
                  }
              }
          
              function locationOf(bytes _data, uint256 _location) internal pure returns (uint256 result) {
                  assembly {
                      result := add(_data, add(0x20, _location))
                  }
              }
          
              function toBytes(bytes4 _sig) internal pure returns (bytes) {
                  bytes memory payload = new bytes(4);
                  assembly { mstore(add(payload, 0x20), _sig) }
                  return payload;
              }
          }
          
          // File: contracts/evmscript/EVMScriptRegistry.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          /* solium-disable function-order */
          // Allow public initialize() to be first
          contract EVMScriptRegistry is IEVMScriptRegistry, EVMScriptRegistryConstants, AragonApp {
              using ScriptHelpers for bytes;
          
              /* Hardcoded constants to save gas
              bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = keccak256("REGISTRY_ADD_EXECUTOR_ROLE");
              bytes32 public constant REGISTRY_MANAGER_ROLE = keccak256("REGISTRY_MANAGER_ROLE");
              */
              bytes32 public constant REGISTRY_ADD_EXECUTOR_ROLE = 0xc4e90f38eea8c4212a009ca7b8947943ba4d4a58d19b683417f65291d1cd9ed2;
              // WARN: Manager can censor all votes and the like happening in an org
              bytes32 public constant REGISTRY_MANAGER_ROLE = 0xf7a450ef335e1892cb42c8ca72e7242359d7711924b75db5717410da3f614aa3;
          
              uint256 internal constant SCRIPT_START_LOCATION = 4;
          
              string private constant ERROR_INEXISTENT_EXECUTOR = "EVMREG_INEXISTENT_EXECUTOR";
              string private constant ERROR_EXECUTOR_ENABLED = "EVMREG_EXECUTOR_ENABLED";
              string private constant ERROR_EXECUTOR_DISABLED = "EVMREG_EXECUTOR_DISABLED";
              string private constant ERROR_SCRIPT_LENGTH_TOO_SHORT = "EVMREG_SCRIPT_LENGTH_TOO_SHORT";
          
              struct ExecutorEntry {
                  IEVMScriptExecutor executor;
                  bool enabled;
              }
          
              uint256 private executorsNextIndex;
              mapping (uint256 => ExecutorEntry) public executors;
          
              event EnableExecutor(uint256 indexed executorId, address indexed executorAddress);
              event DisableExecutor(uint256 indexed executorId, address indexed executorAddress);
          
              modifier executorExists(uint256 _executorId) {
                  require(_executorId > 0 && _executorId < executorsNextIndex, ERROR_INEXISTENT_EXECUTOR);
                  _;
              }
          
              /**
              * @notice Initialize the registry
              */
              function initialize() public onlyInit {
                  initialized();
                  // Create empty record to begin executor IDs at 1
                  executorsNextIndex = 1;
              }
          
              /**
              * @notice Add a new script executor with address `_executor` to the registry
              * @param _executor Address of the IEVMScriptExecutor that will be added to the registry
              * @return id Identifier of the executor in the registry
              */
              function addScriptExecutor(IEVMScriptExecutor _executor) external auth(REGISTRY_ADD_EXECUTOR_ROLE) returns (uint256 id) {
                  uint256 executorId = executorsNextIndex++;
                  executors[executorId] = ExecutorEntry(_executor, true);
                  emit EnableExecutor(executorId, _executor);
                  return executorId;
              }
          
              /**
              * @notice Disable script executor with ID `_executorId`
              * @param _executorId Identifier of the executor in the registry
              */
              function disableScriptExecutor(uint256 _executorId)
                  external
                  authP(REGISTRY_MANAGER_ROLE, arr(_executorId))
              {
                  // Note that we don't need to check for an executor's existence in this case, as only
                  // existing executors can be enabled
                  ExecutorEntry storage executorEntry = executors[_executorId];
                  require(executorEntry.enabled, ERROR_EXECUTOR_DISABLED);
                  executorEntry.enabled = false;
                  emit DisableExecutor(_executorId, executorEntry.executor);
              }
          
              /**
              * @notice Enable script executor with ID `_executorId`
              * @param _executorId Identifier of the executor in the registry
              */
              function enableScriptExecutor(uint256 _executorId)
                  external
                  authP(REGISTRY_MANAGER_ROLE, arr(_executorId))
                  executorExists(_executorId)
              {
                  ExecutorEntry storage executorEntry = executors[_executorId];
                  require(!executorEntry.enabled, ERROR_EXECUTOR_ENABLED);
                  executorEntry.enabled = true;
                  emit EnableExecutor(_executorId, executorEntry.executor);
              }
          
              /**
              * @dev Get the script executor that can execute a particular script based on its first 4 bytes
              * @param _script EVMScript being inspected
              */
              function getScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) {
                  require(_script.length >= SCRIPT_START_LOCATION, ERROR_SCRIPT_LENGTH_TOO_SHORT);
                  uint256 id = _script.getSpecId();
          
                  // Note that we don't need to check for an executor's existence in this case, as only
                  // existing executors can be enabled
                  ExecutorEntry storage entry = executors[id];
                  return entry.enabled ? entry.executor : IEVMScriptExecutor(0);
              }
          }
          
          // File: contracts/evmscript/executors/BaseEVMScriptExecutor.sol
          
          /*
           * SPDX-License-Identifier:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract BaseEVMScriptExecutor is IEVMScriptExecutor, Autopetrified {
              uint256 internal constant SCRIPT_START_LOCATION = 4;
          }
          
          // File: contracts/evmscript/executors/CallsScript.sol
          
          pragma solidity 0.4.24;
          
          // Inspired by https://github.com/reverendus/tx-manager
          
          
          
          
          contract CallsScript is BaseEVMScriptExecutor {
              using ScriptHelpers for bytes;
          
              /* Hardcoded constants to save gas
              bytes32 internal constant EXECUTOR_TYPE = keccak256("CALLS_SCRIPT");
              */
              bytes32 internal constant EXECUTOR_TYPE = 0x2dc858a00f3e417be1394b87c07158e989ec681ce8cc68a9093680ac1a870302;
          
              string private constant ERROR_BLACKLISTED_CALL = "EVMCALLS_BLACKLISTED_CALL";
              string private constant ERROR_INVALID_LENGTH = "EVMCALLS_INVALID_LENGTH";
          
              /* This is manually crafted in assembly
              string private constant ERROR_CALL_REVERTED = "EVMCALLS_CALL_REVERTED";
              */
          
              event LogScriptCall(address indexed sender, address indexed src, address indexed dst);
          
              /**
              * @notice Executes a number of call scripts
              * @param _script [ specId (uint32) ] many calls with this structure ->
              *    [ to (address: 20 bytes) ] [ calldataLength (uint32: 4 bytes) ] [ calldata (calldataLength bytes) ]
              * @param _blacklist Addresses the script cannot call to, or will revert.
              * @return Always returns empty byte array
              */
              function execScript(bytes _script, bytes, address[] _blacklist) external isInitialized returns (bytes) {
                  uint256 location = SCRIPT_START_LOCATION; // first 32 bits are spec id
                  while (location < _script.length) {
                      // Check there's at least address + calldataLength available
                      require(_script.length - location >= 0x18, ERROR_INVALID_LENGTH);
          
                      address contractAddress = _script.addressAt(location);
                      // Check address being called is not blacklist
                      for (uint256 i = 0; i < _blacklist.length; i++) {
                          require(contractAddress != _blacklist[i], ERROR_BLACKLISTED_CALL);
                      }
          
                      // logged before execution to ensure event ordering in receipt
                      // if failed entire execution is reverted regardless
                      emit LogScriptCall(msg.sender, address(this), contractAddress);
          
                      uint256 calldataLength = uint256(_script.uint32At(location + 0x14));
                      uint256 startOffset = location + 0x14 + 0x04;
                      uint256 calldataStart = _script.locationOf(startOffset);
          
                      // compute end of script / next location
                      location = startOffset + calldataLength;
                      require(location <= _script.length, ERROR_INVALID_LENGTH);
          
                      bool success;
                      assembly {
                          success := call(
                              sub(gas, 5000),       // forward gas left - 5000
                              contractAddress,      // address
                              0,                    // no value
                              calldataStart,        // calldata start
                              calldataLength,       // calldata length
                              0,                    // don't write output
                              0                     // don't write output
                          )
          
                          switch success
                          case 0 {
                              let ptr := mload(0x40)
          
                              switch returndatasize
                              case 0 {
                                  // No error data was returned, revert with "EVMCALLS_CALL_REVERTED"
                                  // See remix: doing a `revert("EVMCALLS_CALL_REVERTED")` always results in
                                  // this memory layout
                                  mstore(ptr, 0x08c379a000000000000000000000000000000000000000000000000000000000)         // error identifier
                                  mstore(add(ptr, 0x04), 0x0000000000000000000000000000000000000000000000000000000000000020) // starting offset
                                  mstore(add(ptr, 0x24), 0x0000000000000000000000000000000000000000000000000000000000000016) // reason length
                                  mstore(add(ptr, 0x44), 0x45564d43414c4c535f43414c4c5f524556455254454400000000000000000000) // reason
          
                                  revert(ptr, 100) // 100 = 4 + 3 * 32 (error identifier + 3 words for the ABI encoded error)
                              }
                              default {
                                  // Forward the full error data
                                  returndatacopy(ptr, 0, returndatasize)
                                  revert(ptr, returndatasize)
                              }
                          }
                          default { }
                      }
                  }
                  // No need to allocate empty bytes for the return as this can only be called via an delegatecall
                  // (due to the isInitialized modifier)
              }
          
              function executorType() external pure returns (bytes32) {
                  return EXECUTOR_TYPE;
              }
          }
          
          // File: contracts/factory/EVMScriptRegistryFactory.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          
          contract EVMScriptRegistryFactory is EVMScriptRegistryConstants {
              EVMScriptRegistry public baseReg;
              IEVMScriptExecutor public baseCallScript;
          
              /**
              * @notice Create a new EVMScriptRegistryFactory.
              */
              constructor() public {
                  baseReg = new EVMScriptRegistry();
                  baseCallScript = IEVMScriptExecutor(new CallsScript());
              }
          
              /**
              * @notice Install a new pinned instance of EVMScriptRegistry on `_dao`.
              * @param _dao Kernel
              * @return Installed EVMScriptRegistry
              */
              function newEVMScriptRegistry(Kernel _dao) public returns (EVMScriptRegistry reg) {
                  bytes memory initPayload = abi.encodeWithSelector(reg.initialize.selector);
                  reg = EVMScriptRegistry(_dao.newPinnedAppInstance(EVMSCRIPT_REGISTRY_APP_ID, baseReg, initPayload, true));
          
                  ACL acl = ACL(_dao.acl());
          
                  acl.createPermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE(), this);
          
                  reg.addScriptExecutor(baseCallScript);     // spec 1 = CallsScript
          
                  // Clean up the permissions
                  acl.revokePermission(this, reg, reg.REGISTRY_ADD_EXECUTOR_ROLE());
                  acl.removePermissionManager(reg, reg.REGISTRY_ADD_EXECUTOR_ROLE());
          
                  return reg;
              }
          }
          
          // File: contracts/factory/DAOFactory.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          
          
          contract DAOFactory {
              IKernel public baseKernel;
              IACL public baseACL;
              EVMScriptRegistryFactory public regFactory;
          
              event DeployDAO(address dao);
              event DeployEVMScriptRegistry(address reg);
          
              /**
              * @notice Create a new DAOFactory, creating DAOs with Kernels proxied to `_baseKernel`, ACLs proxied to `_baseACL`, and new EVMScriptRegistries created from `_regFactory`.
              * @param _baseKernel Base Kernel
              * @param _baseACL Base ACL
              * @param _regFactory EVMScriptRegistry factory
              */
              constructor(IKernel _baseKernel, IACL _baseACL, EVMScriptRegistryFactory _regFactory) public {
                  // No need to init as it cannot be killed by devops199
                  if (address(_regFactory) != address(0)) {
                      regFactory = _regFactory;
                  }
          
                  baseKernel = _baseKernel;
                  baseACL = _baseACL;
              }
          
              /**
              * @notice Create a new DAO with `_root` set as the initial admin
              * @param _root Address that will be granted control to setup DAO permissions
              * @return Newly created DAO
              */
              function newDAO(address _root) public returns (Kernel) {
                  Kernel dao = Kernel(new KernelProxy(baseKernel));
          
                  if (address(regFactory) == address(0)) {
                      dao.initialize(baseACL, _root);
                  } else {
                      dao.initialize(baseACL, this);
          
                      ACL acl = ACL(dao.acl());
                      bytes32 permRole = acl.CREATE_PERMISSIONS_ROLE();
                      bytes32 appManagerRole = dao.APP_MANAGER_ROLE();
          
                      acl.grantPermission(regFactory, acl, permRole);
          
                      acl.createPermission(regFactory, dao, appManagerRole, this);
          
                      EVMScriptRegistry reg = regFactory.newEVMScriptRegistry(dao);
                      emit DeployEVMScriptRegistry(address(reg));
          
                      // Clean up permissions
                      // First, completely reset the APP_MANAGER_ROLE
                      acl.revokePermission(regFactory, dao, appManagerRole);
                      acl.removePermissionManager(dao, appManagerRole);
          
                      // Then, make root the only holder and manager of CREATE_PERMISSIONS_ROLE
                      acl.revokePermission(regFactory, acl, permRole);
                      acl.revokePermission(this, acl, permRole);
                      acl.grantPermission(_root, acl, permRole);
                      acl.setPermissionManager(_root, acl, permRole);
                  }
          
                  emit DeployDAO(address(dao));
          
                  return dao;
              }
          }

          File 4 of 5: Kernel
          // File: contracts/acl/IACL.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IACL {
              function initialize(address permissionsCreator) external;
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          }
          
          // File: contracts/common/IVaultRecoverable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IVaultRecoverable {
              event RecoverToVault(address indexed vault, address indexed token, uint256 amount);
          
              function transferToVault(address token) external;
          
              function allowRecoverability(address token) external view returns (bool);
              function getRecoveryVault() external view returns (address);
          }
          
          // File: contracts/kernel/IKernel.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          interface IKernelEvents {
              event SetApp(bytes32 indexed namespace, bytes32 indexed appId, address app);
          }
          
          
          // This should be an interface, but interfaces can't inherit yet :(
          contract IKernel is IKernelEvents, IVaultRecoverable {
              function acl() public view returns (IACL);
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          
              function setApp(bytes32 namespace, bytes32 appId, address app) public;
              function getApp(bytes32 namespace, bytes32 appId) public view returns (address);
          }
          
          // File: contracts/kernel/KernelConstants.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract KernelAppIds {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_APP_ID = apmNamehash("kernel");
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = apmNamehash("acl");
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = apmNamehash("vault");
              */
              bytes32 internal constant KERNEL_CORE_APP_ID = 0x3b4bf6bf3ad5000ecf0f989d5befde585c6860fea3e574a4fab4c49d1c177d9c;
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = 0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a;
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = 0x7e852e0fcfce6551c13800f1e7476f982525c2b5277ba14b24339c68416336d1;
          }
          
          
          contract KernelNamespaceConstants {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_NAMESPACE = keccak256("core");
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = keccak256("base");
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = keccak256("app");
              */
              bytes32 internal constant KERNEL_CORE_NAMESPACE = 0xc681a85306374a5ab27f0bbc385296a54bcd314a1948b6cf61c4ea1bc44bb9f8;
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = 0xf1f3eb40f5bc1ad1344716ced8b8a0431d840b5783aea1fd01786bc26f35ac0f;
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
          }
          
          // File: contracts/kernel/KernelStorage.sol
          
          pragma solidity 0.4.24;
          
          
          contract KernelStorage {
              // namespace => app id => address
              mapping (bytes32 => mapping (bytes32 => address)) public apps;
              bytes32 public recoveryVaultAppId;
          }
          
          // File: contracts/acl/ACLSyntaxSugar.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract ACLSyntaxSugar {
              function arr() internal pure returns (uint256[]) {
                  return new uint256[](0);
              }
          
              function arr(bytes32 _a) internal pure returns (uint256[] r) {
                  return arr(uint256(_a));
              }
          
              function arr(bytes32 _a, bytes32 _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a) internal pure returns (uint256[] r) {
                  return arr(uint256(_a));
              }
          
              function arr(address _a, address _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), _b, _c);
              }
          
              function arr(address _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), _b, _c, _d);
              }
          
              function arr(address _a, uint256 _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a, address _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), _c, _d, _e);
              }
          
              function arr(address _a, address _b, address _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), uint256(_c));
              }
          
              function arr(address _a, address _b, uint256 _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), uint256(_c));
              }
          
              function arr(uint256 _a) internal pure returns (uint256[] r) {
                  r = new uint256[](1);
                  r[0] = _a;
              }
          
              function arr(uint256 _a, uint256 _b) internal pure returns (uint256[] r) {
                  r = new uint256[](2);
                  r[0] = _a;
                  r[1] = _b;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
                  r = new uint256[](3);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
                  r = new uint256[](4);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
                  r[3] = _d;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
                  r = new uint256[](5);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
                  r[3] = _d;
                  r[4] = _e;
              }
          }
          
          
          contract ACLHelpers {
              function decodeParamOp(uint256 _x) internal pure returns (uint8 b) {
                  return uint8(_x >> (8 * 30));
              }
          
              function decodeParamId(uint256 _x) internal pure returns (uint8 b) {
                  return uint8(_x >> (8 * 31));
              }
          
              function decodeParamsList(uint256 _x) internal pure returns (uint32 a, uint32 b, uint32 c) {
                  a = uint32(_x);
                  b = uint32(_x >> (8 * 4));
                  c = uint32(_x >> (8 * 8));
              }
          }
          
          // File: contracts/common/ConversionHelpers.sol
          
          pragma solidity ^0.4.24;
          
          
          library ConversionHelpers {
              string private constant ERROR_IMPROPER_LENGTH = "CONVERSION_IMPROPER_LENGTH";
          
              function dangerouslyCastUintArrayToBytes(uint256[] memory _input) internal pure returns (bytes memory output) {
                  // Force cast the uint256[] into a bytes array, by overwriting its length
                  // Note that the bytes array doesn't need to be initialized as we immediately overwrite it
                  // with the input and a new length. The input becomes invalid from this point forward.
                  uint256 byteLength = _input.length * 32;
                  assembly {
                      output := _input
                      mstore(output, byteLength)
                  }
              }
          
              function dangerouslyCastBytesToUintArray(bytes memory _input) internal pure returns (uint256[] memory output) {
                  // Force cast the bytes array into a uint256[], by overwriting its length
                  // Note that the uint256[] doesn't need to be initialized as we immediately overwrite it
                  // with the input and a new length. The input becomes invalid from this point forward.
                  uint256 intsLength = _input.length / 32;
                  require(_input.length == intsLength * 32, ERROR_IMPROPER_LENGTH);
          
                  assembly {
                      output := _input
                      mstore(output, intsLength)
                  }
              }
          }
          
          // File: contracts/common/IsContract.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract IsContract {
              /*
              * NOTE: this should NEVER be used for authentication
              * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize).
              *
              * This is only intended to be used as a sanity check that an address is actually a contract,
              * RATHER THAN an address not being a contract.
              */
              function isContract(address _target) internal view returns (bool) {
                  if (_target == address(0)) {
                      return false;
                  }
          
                  uint256 size;
                  assembly { size := extcodesize(_target) }
                  return size > 0;
              }
          }
          
          // File: contracts/common/Uint256Helpers.sol
          
          pragma solidity ^0.4.24;
          
          
          library Uint256Helpers {
              uint256 private constant MAX_UINT64 = uint64(-1);
          
              string private constant ERROR_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG";
          
              function toUint64(uint256 a) internal pure returns (uint64) {
                  require(a <= MAX_UINT64, ERROR_NUMBER_TOO_BIG);
                  return uint64(a);
              }
          }
          
          // File: contracts/common/TimeHelpers.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract TimeHelpers {
              using Uint256Helpers for uint256;
          
              /**
              * @dev Returns the current block number.
              *      Using a function rather than `block.number` allows us to easily mock the block number in
              *      tests.
              */
              function getBlockNumber() internal view returns (uint256) {
                  return block.number;
              }
          
              /**
              * @dev Returns the current block number, converted to uint64.
              *      Using a function rather than `block.number` allows us to easily mock the block number in
              *      tests.
              */
              function getBlockNumber64() internal view returns (uint64) {
                  return getBlockNumber().toUint64();
              }
          
              /**
              * @dev Returns the current timestamp.
              *      Using a function rather than `block.timestamp` allows us to easily mock it in
              *      tests.
              */
              function getTimestamp() internal view returns (uint256) {
                  return block.timestamp; // solium-disable-line security/no-block-members
              }
          
              /**
              * @dev Returns the current timestamp, converted to uint64.
              *      Using a function rather than `block.timestamp` allows us to easily mock it in
              *      tests.
              */
              function getTimestamp64() internal view returns (uint64) {
                  return getTimestamp().toUint64();
              }
          }
          
          // File: contracts/common/UnstructuredStorage.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          library UnstructuredStorage {
              function getStorageBool(bytes32 position) internal view returns (bool data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageAddress(bytes32 position) internal view returns (address data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageUint256(bytes32 position) internal view returns (uint256 data) {
                  assembly { data := sload(position) }
              }
          
              function setStorageBool(bytes32 position, bool data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageAddress(bytes32 position, address data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageBytes32(bytes32 position, bytes32 data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageUint256(bytes32 position, uint256 data) internal {
                  assembly { sstore(position, data) }
              }
          }
          
          // File: contracts/common/Initializable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract Initializable is TimeHelpers {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.initializable.initializationBlock")
              bytes32 internal constant INITIALIZATION_BLOCK_POSITION = 0xebb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e;
          
              string private constant ERROR_ALREADY_INITIALIZED = "INIT_ALREADY_INITIALIZED";
              string private constant ERROR_NOT_INITIALIZED = "INIT_NOT_INITIALIZED";
          
              modifier onlyInit {
                  require(getInitializationBlock() == 0, ERROR_ALREADY_INITIALIZED);
                  _;
              }
          
              modifier isInitialized {
                  require(hasInitialized(), ERROR_NOT_INITIALIZED);
                  _;
              }
          
              /**
              * @return Block number in which the contract was initialized
              */
              function getInitializationBlock() public view returns (uint256) {
                  return INITIALIZATION_BLOCK_POSITION.getStorageUint256();
              }
          
              /**
              * @return Whether the contract has been initialized by the time of the current block
              */
              function hasInitialized() public view returns (bool) {
                  uint256 initializationBlock = getInitializationBlock();
                  return initializationBlock != 0 && getBlockNumber() >= initializationBlock;
              }
          
              /**
              * @dev Function to be called by top level contract after initialization has finished.
              */
              function initialized() internal onlyInit {
                  INITIALIZATION_BLOCK_POSITION.setStorageUint256(getBlockNumber());
              }
          
              /**
              * @dev Function to be called by top level contract after initialization to enable the contract
              *      at a future block number rather than immediately.
              */
              function initializedAt(uint256 _blockNumber) internal onlyInit {
                  INITIALIZATION_BLOCK_POSITION.setStorageUint256(_blockNumber);
              }
          }
          
          // File: contracts/common/Petrifiable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract Petrifiable is Initializable {
              // Use block UINT256_MAX (which should be never) as the initializable date
              uint256 internal constant PETRIFIED_BLOCK = uint256(-1);
          
              function isPetrified() public view returns (bool) {
                  return getInitializationBlock() == PETRIFIED_BLOCK;
              }
          
              /**
              * @dev Function to be called by top level contract to prevent being initialized.
              *      Useful for freezing base contracts when they're used behind proxies.
              */
              function petrify() internal onlyInit {
                  initializedAt(PETRIFIED_BLOCK);
              }
          }
          
          // File: contracts/lib/token/ERC20.sol
          
          // See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/a9f910d34f0ab33a1ae5e714f69f9596a02b4d91/contracts/token/ERC20/ERC20.sol
          
          pragma solidity ^0.4.24;
          
          
          /**
           * @title ERC20 interface
           * @dev see https://github.com/ethereum/EIPs/issues/20
           */
          contract ERC20 {
              function totalSupply() public view returns (uint256);
          
              function balanceOf(address _who) public view returns (uint256);
          
              function allowance(address _owner, address _spender)
                  public view returns (uint256);
          
              function transfer(address _to, uint256 _value) public returns (bool);
          
              function approve(address _spender, uint256 _value)
                  public returns (bool);
          
              function transferFrom(address _from, address _to, uint256 _value)
                  public returns (bool);
          
              event Transfer(
                  address indexed from,
                  address indexed to,
                  uint256 value
              );
          
              event Approval(
                  address indexed owner,
                  address indexed spender,
                  uint256 value
              );
          }
          
          // File: contracts/common/EtherTokenConstant.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          // aragonOS and aragon-apps rely on address(0) to denote native ETH, in
          // contracts where both tokens and ETH are accepted
          contract EtherTokenConstant {
              address internal constant ETH = address(0);
          }
          
          // File: contracts/common/SafeERC20.sol
          
          // Inspired by AdEx (https://github.com/AdExNetwork/adex-protocol-eth/blob/b9df617829661a7518ee10f4cb6c4108659dd6d5/contracts/libs/SafeERC20.sol)
          // and 0x (https://github.com/0xProject/0x-monorepo/blob/737d1dc54d72872e24abce5a1dbe1b66d35fa21a/contracts/protocol/contracts/protocol/AssetProxy/ERC20Proxy.sol#L143)
          
          pragma solidity ^0.4.24;
          
          
          
          library SafeERC20 {
              // Before 0.5, solidity has a mismatch between `address.transfer()` and `token.transfer()`:
              // https://github.com/ethereum/solidity/issues/3544
              bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb;
          
              string private constant ERROR_TOKEN_BALANCE_REVERTED = "SAFE_ERC_20_BALANCE_REVERTED";
              string private constant ERROR_TOKEN_ALLOWANCE_REVERTED = "SAFE_ERC_20_ALLOWANCE_REVERTED";
          
              function invokeAndCheckSuccess(address _addr, bytes memory _calldata)
                  private
                  returns (bool)
              {
                  bool ret;
                  assembly {
                      let ptr := mload(0x40)    // free memory pointer
          
                      let success := call(
                          gas,                  // forward all gas
                          _addr,                // address
                          0,                    // no value
                          add(_calldata, 0x20), // calldata start
                          mload(_calldata),     // calldata length
                          ptr,                  // write output over free memory
                          0x20                  // uint256 return
                      )
          
                      if gt(success, 0) {
                          // Check number of bytes returned from last function call
                          switch returndatasize
          
                          // No bytes returned: assume success
                          case 0 {
                              ret := 1
                          }
          
                          // 32 bytes returned: check if non-zero
                          case 0x20 {
                              // Only return success if returned data was true
                              // Already have output in ptr
                              ret := eq(mload(ptr), 1)
                          }
          
                          // Not sure what was returned: don't mark as success
                          default { }
                      }
                  }
                  return ret;
              }
          
              function staticInvoke(address _addr, bytes memory _calldata)
                  private
                  view
                  returns (bool, uint256)
              {
                  bool success;
                  uint256 ret;
                  assembly {
                      let ptr := mload(0x40)    // free memory pointer
          
                      success := staticcall(
                          gas,                  // forward all gas
                          _addr,                // address
                          add(_calldata, 0x20), // calldata start
                          mload(_calldata),     // calldata length
                          ptr,                  // write output over free memory
                          0x20                  // uint256 return
                      )
          
                      if gt(success, 0) {
                          ret := mload(ptr)
                      }
                  }
                  return (success, ret);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) {
                  bytes memory transferCallData = abi.encodeWithSelector(
                      TRANSFER_SELECTOR,
                      _to,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, transferCallData);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) {
                  bytes memory transferFromCallData = abi.encodeWithSelector(
                      _token.transferFrom.selector,
                      _from,
                      _to,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, transferFromCallData);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) {
                  bytes memory approveCallData = abi.encodeWithSelector(
                      _token.approve.selector,
                      _spender,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, approveCallData);
              }
          
              /**
              * @dev Static call into ERC20.balanceOf().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticBalanceOf(ERC20 _token, address _owner) internal view returns (uint256) {
                  bytes memory balanceOfCallData = abi.encodeWithSelector(
                      _token.balanceOf.selector,
                      _owner
                  );
          
                  (bool success, uint256 tokenBalance) = staticInvoke(_token, balanceOfCallData);
                  require(success, ERROR_TOKEN_BALANCE_REVERTED);
          
                  return tokenBalance;
              }
          
              /**
              * @dev Static call into ERC20.allowance().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticAllowance(ERC20 _token, address _owner, address _spender) internal view returns (uint256) {
                  bytes memory allowanceCallData = abi.encodeWithSelector(
                      _token.allowance.selector,
                      _owner,
                      _spender
                  );
          
                  (bool success, uint256 allowance) = staticInvoke(_token, allowanceCallData);
                  require(success, ERROR_TOKEN_ALLOWANCE_REVERTED);
          
                  return allowance;
              }
          
              /**
              * @dev Static call into ERC20.totalSupply().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticTotalSupply(ERC20 _token) internal view returns (uint256) {
                  bytes memory totalSupplyCallData = abi.encodeWithSelector(_token.totalSupply.selector);
          
                  (bool success, uint256 totalSupply) = staticInvoke(_token, totalSupplyCallData);
                  require(success, ERROR_TOKEN_ALLOWANCE_REVERTED);
          
                  return totalSupply;
              }
          }
          
          // File: contracts/common/VaultRecoverable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          
          
          
          contract VaultRecoverable is IVaultRecoverable, EtherTokenConstant, IsContract {
              using SafeERC20 for ERC20;
          
              string private constant ERROR_DISALLOWED = "RECOVER_DISALLOWED";
              string private constant ERROR_VAULT_NOT_CONTRACT = "RECOVER_VAULT_NOT_CONTRACT";
              string private constant ERROR_TOKEN_TRANSFER_FAILED = "RECOVER_TOKEN_TRANSFER_FAILED";
          
              /**
               * @notice Send funds to recovery Vault. This contract should never receive funds,
               *         but in case it does, this function allows one to recover them.
               * @param _token Token balance to be sent to recovery vault.
               */
              function transferToVault(address _token) external {
                  require(allowRecoverability(_token), ERROR_DISALLOWED);
                  address vault = getRecoveryVault();
                  require(isContract(vault), ERROR_VAULT_NOT_CONTRACT);
          
                  uint256 balance;
                  if (_token == ETH) {
                      balance = address(this).balance;
                      vault.transfer(balance);
                  } else {
                      ERC20 token = ERC20(_token);
                      balance = token.staticBalanceOf(this);
                      require(token.safeTransfer(vault, balance), ERROR_TOKEN_TRANSFER_FAILED);
                  }
          
                  emit RecoverToVault(vault, _token, balance);
              }
          
              /**
              * @dev By default deriving from AragonApp makes it recoverable
              * @param token Token address that would be recovered
              * @return bool whether the app allows the recovery
              */
              function allowRecoverability(address token) public view returns (bool) {
                  return true;
              }
          
              // Cast non-implemented interface to be public so we can use it internally
              function getRecoveryVault() public view returns (address);
          }
          
          // File: contracts/apps/AppStorage.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract AppStorage {
              using UnstructuredStorage for bytes32;
          
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_POSITION = keccak256("aragonOS.appStorage.kernel");
              bytes32 internal constant APP_ID_POSITION = keccak256("aragonOS.appStorage.appId");
              */
              bytes32 internal constant KERNEL_POSITION = 0x4172f0f7d2289153072b0a6ca36959e0cbe2efc3afe50fc81636caa96338137b;
              bytes32 internal constant APP_ID_POSITION = 0xd625496217aa6a3453eecb9c3489dc5a53e6c67b444329ea2b2cbc9ff547639b;
          
              function kernel() public view returns (IKernel) {
                  return IKernel(KERNEL_POSITION.getStorageAddress());
              }
          
              function appId() public view returns (bytes32) {
                  return APP_ID_POSITION.getStorageBytes32();
              }
          
              function setKernel(IKernel _kernel) internal {
                  KERNEL_POSITION.setStorageAddress(address(_kernel));
              }
          
              function setAppId(bytes32 _appId) internal {
                  APP_ID_POSITION.setStorageBytes32(_appId);
              }
          }
          
          // File: contracts/lib/misc/ERCProxy.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract ERCProxy {
              uint256 internal constant FORWARDING = 1;
              uint256 internal constant UPGRADEABLE = 2;
          
              function proxyType() public pure returns (uint256 proxyTypeId);
              function implementation() public view returns (address codeAddr);
          }
          
          // File: contracts/common/DelegateProxy.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract DelegateProxy is ERCProxy, IsContract {
              uint256 internal constant FWD_GAS_LIMIT = 10000;
          
              /**
              * @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!)
              * @param _dst Destination address to perform the delegatecall
              * @param _calldata Calldata for the delegatecall
              */
              function delegatedFwd(address _dst, bytes _calldata) internal {
                  require(isContract(_dst));
                  uint256 fwdGasLimit = FWD_GAS_LIMIT;
          
                  assembly {
                      let result := delegatecall(sub(gas, fwdGasLimit), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0)
                      let size := returndatasize
                      let ptr := mload(0x40)
                      returndatacopy(ptr, 0, size)
          
                      // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas.
                      // if the call returned error data, forward it
                      switch result case 0 { revert(ptr, size) }
                      default { return(ptr, size) }
                  }
              }
          }
          
          // File: contracts/common/DepositableStorage.sol
          
          pragma solidity 0.4.24;
          
          
          
          contract DepositableStorage {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.depositableStorage.depositable")
              bytes32 internal constant DEPOSITABLE_POSITION = 0x665fd576fbbe6f247aff98f5c94a561e3f71ec2d3c988d56f12d342396c50cea;
          
              function isDepositable() public view returns (bool) {
                  return DEPOSITABLE_POSITION.getStorageBool();
              }
          
              function setDepositable(bool _depositable) internal {
                  DEPOSITABLE_POSITION.setStorageBool(_depositable);
              }
          }
          
          // File: contracts/common/DepositableDelegateProxy.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract DepositableDelegateProxy is DepositableStorage, DelegateProxy {
              event ProxyDeposit(address sender, uint256 value);
          
              function () external payable {
                  uint256 forwardGasThreshold = FWD_GAS_LIMIT;
                  bytes32 isDepositablePosition = DEPOSITABLE_POSITION;
          
                  // Optimized assembly implementation to prevent EIP-1884 from breaking deposits, reference code in Solidity:
                  // https://github.com/aragon/aragonOS/blob/v4.2.1/contracts/common/DepositableDelegateProxy.sol#L10-L20
                  assembly {
                      // Continue only if the gas left is lower than the threshold for forwarding to the implementation code,
                      // otherwise continue outside of the assembly block.
                      if lt(gas, forwardGasThreshold) {
                          // Only accept the deposit and emit an event if all of the following are true:
                          // the proxy accepts deposits (isDepositable), msg.data.length == 0, and msg.value > 0
                          if and(and(sload(isDepositablePosition), iszero(calldatasize)), gt(callvalue, 0)) {
                              // Equivalent Solidity code for emitting the event:
                              // emit ProxyDeposit(msg.sender, msg.value);
          
                              let logData := mload(0x40) // free memory pointer
                              mstore(logData, caller) // add 'msg.sender' to the log data (first event param)
                              mstore(add(logData, 0x20), callvalue) // add 'msg.value' to the log data (second event param)
          
                              // Emit an event with one topic to identify the event: keccak256('ProxyDeposit(address,uint256)') = 0x15ee...dee1
                              log1(logData, 0x40, 0x15eeaa57c7bd188c1388020bcadc2c436ec60d647d36ef5b9eb3c742217ddee1)
          
                              stop() // Stop. Exits execution context
                          }
          
                          // If any of above checks failed, revert the execution (if ETH was sent, it is returned to the sender)
                          revert(0, 0)
                      }
                  }
          
                  address target = implementation();
                  delegatedFwd(target, msg.data);
              }
          }
          
          // File: contracts/apps/AppProxyBase.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          contract AppProxyBase is AppStorage, DepositableDelegateProxy, KernelNamespaceConstants {
              /**
              * @dev Initialize AppProxy
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload) public {
                  setKernel(_kernel);
                  setAppId(_appId);
          
                  // Implicit check that kernel is actually a Kernel
                  // The EVM doesn't actually provide a way for us to make sure, but we can force a revert to
                  // occur if the kernel is set to 0x0 or a non-code address when we try to call a method on
                  // it.
                  address appCode = getAppBase(_appId);
          
                  // If initialize payload is provided, it will be executed
                  if (_initializePayload.length > 0) {
                      require(isContract(appCode));
                      // Cannot make delegatecall as a delegateproxy.delegatedFwd as it
                      // returns ending execution context and halts contract deployment
                      require(appCode.delegatecall(_initializePayload));
                  }
              }
          
              function getAppBase(bytes32 _appId) internal view returns (address) {
                  return kernel().getApp(KERNEL_APP_BASES_NAMESPACE, _appId);
              }
          }
          
          // File: contracts/apps/AppProxyUpgradeable.sol
          
          pragma solidity 0.4.24;
          
          
          
          contract AppProxyUpgradeable is AppProxyBase {
              /**
              * @dev Initialize AppProxyUpgradeable (makes it an upgradeable Aragon app)
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload)
                  AppProxyBase(_kernel, _appId, _initializePayload)
                  public // solium-disable-line visibility-first
              {
                  // solium-disable-previous-line no-empty-blocks
              }
          
              /**
               * @dev ERC897, the address the proxy would delegate calls to
               */
              function implementation() public view returns (address) {
                  return getAppBase(appId());
              }
          
              /**
               * @dev ERC897, whether it is a forwarding (1) or an upgradeable (2) proxy
               */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                  return UPGRADEABLE;
              }
          }
          
          // File: contracts/apps/AppProxyPinned.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          contract AppProxyPinned is IsContract, AppProxyBase {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.appStorage.pinnedCode")
              bytes32 internal constant PINNED_CODE_POSITION = 0xdee64df20d65e53d7f51cb6ab6d921a0a6a638a91e942e1d8d02df28e31c038e;
          
              /**
              * @dev Initialize AppProxyPinned (makes it an un-upgradeable Aragon app)
              * @param _kernel Reference to organization kernel for the app
              * @param _appId Identifier for app
              * @param _initializePayload Payload for call to be made after setup to initialize
              */
              constructor(IKernel _kernel, bytes32 _appId, bytes _initializePayload)
                  AppProxyBase(_kernel, _appId, _initializePayload)
                  public // solium-disable-line visibility-first
              {
                  setPinnedCode(getAppBase(_appId));
                  require(isContract(pinnedCode()));
              }
          
              /**
               * @dev ERC897, the address the proxy would delegate calls to
               */
              function implementation() public view returns (address) {
                  return pinnedCode();
              }
          
              /**
               * @dev ERC897, whether it is a forwarding (1) or an upgradeable (2) proxy
               */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                  return FORWARDING;
              }
          
              function setPinnedCode(address _pinnedCode) internal {
                  PINNED_CODE_POSITION.setStorageAddress(_pinnedCode);
              }
          
              function pinnedCode() internal view returns (address) {
                  return PINNED_CODE_POSITION.getStorageAddress();
              }
          }
          
          // File: contracts/factory/AppProxyFactory.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          contract AppProxyFactory {
              event NewAppProxy(address proxy, bool isUpgradeable, bytes32 appId);
          
              /**
              * @notice Create a new upgradeable app instance on `_kernel` with identifier `_appId`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @return AppProxyUpgradeable
              */
              function newAppProxy(IKernel _kernel, bytes32 _appId) public returns (AppProxyUpgradeable) {
                  return newAppProxy(_kernel, _appId, new bytes(0));
              }
          
              /**
              * @notice Create a new upgradeable app instance on `_kernel` with identifier `_appId` and initialization payload `_initializePayload`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @return AppProxyUpgradeable
              */
              function newAppProxy(IKernel _kernel, bytes32 _appId, bytes _initializePayload) public returns (AppProxyUpgradeable) {
                  AppProxyUpgradeable proxy = new AppProxyUpgradeable(_kernel, _appId, _initializePayload);
                  emit NewAppProxy(address(proxy), true, _appId);
                  return proxy;
              }
          
              /**
              * @notice Create a new pinned app instance on `_kernel` with identifier `_appId`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @return AppProxyPinned
              */
              function newAppProxyPinned(IKernel _kernel, bytes32 _appId) public returns (AppProxyPinned) {
                  return newAppProxyPinned(_kernel, _appId, new bytes(0));
              }
          
              /**
              * @notice Create a new pinned app instance on `_kernel` with identifier `_appId` and initialization payload `_initializePayload`
              * @param _kernel App's Kernel reference
              * @param _appId Identifier for app
              * @param _initializePayload Proxy initialization payload
              * @return AppProxyPinned
              */
              function newAppProxyPinned(IKernel _kernel, bytes32 _appId, bytes _initializePayload) public returns (AppProxyPinned) {
                  AppProxyPinned proxy = new AppProxyPinned(_kernel, _appId, _initializePayload);
                  emit NewAppProxy(address(proxy), false, _appId);
                  return proxy;
              }
          }
          
          // File: contracts/kernel/Kernel.sol
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          
          
          
          
          
          
          
          // solium-disable-next-line max-len
          contract Kernel is IKernel, KernelStorage, KernelAppIds, KernelNamespaceConstants, Petrifiable, IsContract, VaultRecoverable, AppProxyFactory, ACLSyntaxSugar {
              /* Hardcoded constants to save gas
              bytes32 public constant APP_MANAGER_ROLE = keccak256("APP_MANAGER_ROLE");
              */
              bytes32 public constant APP_MANAGER_ROLE = 0xb6d92708f3d4817afc106147d969e229ced5c46e65e0a5002a0d391287762bd0;
          
              string private constant ERROR_APP_NOT_CONTRACT = "KERNEL_APP_NOT_CONTRACT";
              string private constant ERROR_INVALID_APP_CHANGE = "KERNEL_INVALID_APP_CHANGE";
              string private constant ERROR_AUTH_FAILED = "KERNEL_AUTH_FAILED";
          
              /**
              * @dev Constructor that allows the deployer to choose if the base instance should be petrified immediately.
              * @param _shouldPetrify Immediately petrify this instance so that it can never be initialized
              */
              constructor(bool _shouldPetrify) public {
                  if (_shouldPetrify) {
                      petrify();
                  }
              }
          
              /**
              * @dev Initialize can only be called once. It saves the block number in which it was initialized.
              * @notice Initialize this kernel instance along with its ACL and set `_permissionsCreator` as the entity that can create other permissions
              * @param _baseAcl Address of base ACL app
              * @param _permissionsCreator Entity that will be given permission over createPermission
              */
              function initialize(IACL _baseAcl, address _permissionsCreator) public onlyInit {
                  initialized();
          
                  // Set ACL base
                  _setApp(KERNEL_APP_BASES_NAMESPACE, KERNEL_DEFAULT_ACL_APP_ID, _baseAcl);
          
                  // Create ACL instance and attach it as the default ACL app
                  IACL acl = IACL(newAppProxy(this, KERNEL_DEFAULT_ACL_APP_ID));
                  acl.initialize(_permissionsCreator);
                  _setApp(KERNEL_APP_ADDR_NAMESPACE, KERNEL_DEFAULT_ACL_APP_ID, acl);
          
                  recoveryVaultAppId = KERNEL_DEFAULT_VAULT_APP_ID;
              }
          
              /**
              * @dev Create a new instance of an app linked to this kernel
              * @notice Create a new upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @return AppProxy instance
              */
              function newAppInstance(bytes32 _appId, address _appBase)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  return newAppInstance(_appId, _appBase, new bytes(0), false);
              }
          
              /**
              * @dev Create a new instance of an app linked to this kernel and set its base
              *      implementation if it was not already set
              * @notice Create a new upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`. `_setDefault ? 'Also sets it as the default app instance.':''`
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @param _initializePayload Payload for call made by the proxy during its construction to initialize
              * @param _setDefault Whether the app proxy app is the default one.
              *        Useful when the Kernel needs to know of an instance of a particular app,
              *        like Vault for escape hatch mechanism.
              * @return AppProxy instance
              */
              function newAppInstance(bytes32 _appId, address _appBase, bytes _initializePayload, bool _setDefault)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  _setAppIfNew(KERNEL_APP_BASES_NAMESPACE, _appId, _appBase);
                  appProxy = newAppProxy(this, _appId, _initializePayload);
                  // By calling setApp directly and not the internal functions, we make sure the params are checked
                  // and it will only succeed if sender has permissions to set something to the namespace.
                  if (_setDefault) {
                      setApp(KERNEL_APP_ADDR_NAMESPACE, _appId, appProxy);
                  }
              }
          
              /**
              * @dev Create a new pinned instance of an app linked to this kernel
              * @notice Create a new non-upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`.
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @return AppProxy instance
              */
              function newPinnedAppInstance(bytes32 _appId, address _appBase)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  return newPinnedAppInstance(_appId, _appBase, new bytes(0), false);
              }
          
              /**
              * @dev Create a new pinned instance of an app linked to this kernel and set
              *      its base implementation if it was not already set
              * @notice Create a new non-upgradeable instance of `_appId` app linked to the Kernel, setting its code to `_appBase`. `_setDefault ? 'Also sets it as the default app instance.':''`
              * @param _appId Identifier for app
              * @param _appBase Address of the app's base implementation
              * @param _initializePayload Payload for call made by the proxy during its construction to initialize
              * @param _setDefault Whether the app proxy app is the default one.
              *        Useful when the Kernel needs to know of an instance of a particular app,
              *        like Vault for escape hatch mechanism.
              * @return AppProxy instance
              */
              function newPinnedAppInstance(bytes32 _appId, address _appBase, bytes _initializePayload, bool _setDefault)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_BASES_NAMESPACE, _appId))
                  returns (ERCProxy appProxy)
              {
                  _setAppIfNew(KERNEL_APP_BASES_NAMESPACE, _appId, _appBase);
                  appProxy = newAppProxyPinned(this, _appId, _initializePayload);
                  // By calling setApp directly and not the internal functions, we make sure the params are checked
                  // and it will only succeed if sender has permissions to set something to the namespace.
                  if (_setDefault) {
                      setApp(KERNEL_APP_ADDR_NAMESPACE, _appId, appProxy);
                  }
              }
          
              /**
              * @dev Set the resolving address of an app instance or base implementation
              * @notice Set the resolving address of `_appId` in namespace `_namespace` to `_app`
              * @param _namespace App namespace to use
              * @param _appId Identifier for app
              * @param _app Address of the app instance or base implementation
              * @return ID of app
              */
              function setApp(bytes32 _namespace, bytes32 _appId, address _app)
                  public
                  auth(APP_MANAGER_ROLE, arr(_namespace, _appId))
              {
                  _setApp(_namespace, _appId, _app);
              }
          
              /**
              * @dev Set the default vault id for the escape hatch mechanism
              * @param _recoveryVaultAppId Identifier of the recovery vault app
              */
              function setRecoveryVaultAppId(bytes32 _recoveryVaultAppId)
                  public
                  auth(APP_MANAGER_ROLE, arr(KERNEL_APP_ADDR_NAMESPACE, _recoveryVaultAppId))
              {
                  recoveryVaultAppId = _recoveryVaultAppId;
              }
          
              // External access to default app id and namespace constants to mimic default getters for constants
              /* solium-disable function-order, mixedcase */
              function CORE_NAMESPACE() external pure returns (bytes32) { return KERNEL_CORE_NAMESPACE; }
              function APP_BASES_NAMESPACE() external pure returns (bytes32) { return KERNEL_APP_BASES_NAMESPACE; }
              function APP_ADDR_NAMESPACE() external pure returns (bytes32) { return KERNEL_APP_ADDR_NAMESPACE; }
              function KERNEL_APP_ID() external pure returns (bytes32) { return KERNEL_CORE_APP_ID; }
              function DEFAULT_ACL_APP_ID() external pure returns (bytes32) { return KERNEL_DEFAULT_ACL_APP_ID; }
              /* solium-enable function-order, mixedcase */
          
              /**
              * @dev Get the address of an app instance or base implementation
              * @param _namespace App namespace to use
              * @param _appId Identifier for app
              * @return Address of the app
              */
              function getApp(bytes32 _namespace, bytes32 _appId) public view returns (address) {
                  return apps[_namespace][_appId];
              }
          
              /**
              * @dev Get the address of the recovery Vault instance (to recover funds)
              * @return Address of the Vault
              */
              function getRecoveryVault() public view returns (address) {
                  return apps[KERNEL_APP_ADDR_NAMESPACE][recoveryVaultAppId];
              }
          
              /**
              * @dev Get the installed ACL app
              * @return ACL app
              */
              function acl() public view returns (IACL) {
                  return IACL(getApp(KERNEL_APP_ADDR_NAMESPACE, KERNEL_DEFAULT_ACL_APP_ID));
              }
          
              /**
              * @dev Function called by apps to check ACL on kernel or to check permission status
              * @param _who Sender of the original call
              * @param _where Address of the app
              * @param _what Identifier for a group of actions in app
              * @param _how Extra data for ACL auth
              * @return Boolean indicating whether the ACL allows the role or not.
              *         Always returns false if the kernel hasn't been initialized yet.
              */
              function hasPermission(address _who, address _where, bytes32 _what, bytes _how) public view returns (bool) {
                  IACL defaultAcl = acl();
                  return address(defaultAcl) != address(0) && // Poor man's initialization check (saves gas)
                      defaultAcl.hasPermission(_who, _where, _what, _how);
              }
          
              function _setApp(bytes32 _namespace, bytes32 _appId, address _app) internal {
                  require(isContract(_app), ERROR_APP_NOT_CONTRACT);
                  apps[_namespace][_appId] = _app;
                  emit SetApp(_namespace, _appId, _app);
              }
          
              function _setAppIfNew(bytes32 _namespace, bytes32 _appId, address _app) internal {
                  address app = getApp(_namespace, _appId);
                  if (app != address(0)) {
                      // The only way to set an app is if it passes the isContract check, so no need to check it again
                      require(app == _app, ERROR_INVALID_APP_CHANGE);
                  } else {
                      _setApp(_namespace, _appId, _app);
                  }
              }
          
              modifier auth(bytes32 _role, uint256[] memory _params) {
                  require(
                      hasPermission(msg.sender, address(this), _role, ConversionHelpers.dangerouslyCastUintArrayToBytes(_params)),
                      ERROR_AUTH_FAILED
                  );
                  _;
              }
          }

          File 5 of 5: TokenManager
          // File: @aragon/os/contracts/common/UnstructuredStorage.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          library UnstructuredStorage {
              function getStorageBool(bytes32 position) internal view returns (bool data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageAddress(bytes32 position) internal view returns (address data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) {
                  assembly { data := sload(position) }
              }
          
              function getStorageUint256(bytes32 position) internal view returns (uint256 data) {
                  assembly { data := sload(position) }
              }
          
              function setStorageBool(bytes32 position, bool data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageAddress(bytes32 position, address data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageBytes32(bytes32 position, bytes32 data) internal {
                  assembly { sstore(position, data) }
              }
          
              function setStorageUint256(bytes32 position, uint256 data) internal {
                  assembly { sstore(position, data) }
              }
          }
          
          // File: @aragon/os/contracts/acl/IACL.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IACL {
              function initialize(address permissionsCreator) external;
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          }
          
          // File: @aragon/os/contracts/common/IVaultRecoverable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IVaultRecoverable {
              event RecoverToVault(address indexed vault, address indexed token, uint256 amount);
          
              function transferToVault(address token) external;
          
              function allowRecoverability(address token) external view returns (bool);
              function getRecoveryVault() external view returns (address);
          }
          
          // File: @aragon/os/contracts/kernel/IKernel.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          interface IKernelEvents {
              event SetApp(bytes32 indexed namespace, bytes32 indexed appId, address app);
          }
          
          
          // This should be an interface, but interfaces can't inherit yet :(
          contract IKernel is IKernelEvents, IVaultRecoverable {
              function acl() public view returns (IACL);
              function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
          
              function setApp(bytes32 namespace, bytes32 appId, address app) public;
              function getApp(bytes32 namespace, bytes32 appId) public view returns (address);
          }
          
          // File: @aragon/os/contracts/apps/AppStorage.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract AppStorage {
              using UnstructuredStorage for bytes32;
          
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_POSITION = keccak256("aragonOS.appStorage.kernel");
              bytes32 internal constant APP_ID_POSITION = keccak256("aragonOS.appStorage.appId");
              */
              bytes32 internal constant KERNEL_POSITION = 0x4172f0f7d2289153072b0a6ca36959e0cbe2efc3afe50fc81636caa96338137b;
              bytes32 internal constant APP_ID_POSITION = 0xd625496217aa6a3453eecb9c3489dc5a53e6c67b444329ea2b2cbc9ff547639b;
          
              function kernel() public view returns (IKernel) {
                  return IKernel(KERNEL_POSITION.getStorageAddress());
              }
          
              function appId() public view returns (bytes32) {
                  return APP_ID_POSITION.getStorageBytes32();
              }
          
              function setKernel(IKernel _kernel) internal {
                  KERNEL_POSITION.setStorageAddress(address(_kernel));
              }
          
              function setAppId(bytes32 _appId) internal {
                  APP_ID_POSITION.setStorageBytes32(_appId);
              }
          }
          
          // File: @aragon/os/contracts/acl/ACLSyntaxSugar.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract ACLSyntaxSugar {
              function arr() internal pure returns (uint256[]) {
                  return new uint256[](0);
              }
          
              function arr(bytes32 _a) internal pure returns (uint256[] r) {
                  return arr(uint256(_a));
              }
          
              function arr(bytes32 _a, bytes32 _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a) internal pure returns (uint256[] r) {
                  return arr(uint256(_a));
              }
          
              function arr(address _a, address _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), _b, _c);
              }
          
              function arr(address _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), _b, _c, _d);
              }
          
              function arr(address _a, uint256 _b) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b));
              }
          
              function arr(address _a, address _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), _c, _d, _e);
              }
          
              function arr(address _a, address _b, address _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), uint256(_c));
              }
          
              function arr(address _a, address _b, uint256 _c) internal pure returns (uint256[] r) {
                  return arr(uint256(_a), uint256(_b), uint256(_c));
              }
          
              function arr(uint256 _a) internal pure returns (uint256[] r) {
                  r = new uint256[](1);
                  r[0] = _a;
              }
          
              function arr(uint256 _a, uint256 _b) internal pure returns (uint256[] r) {
                  r = new uint256[](2);
                  r[0] = _a;
                  r[1] = _b;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c) internal pure returns (uint256[] r) {
                  r = new uint256[](3);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d) internal pure returns (uint256[] r) {
                  r = new uint256[](4);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
                  r[3] = _d;
              }
          
              function arr(uint256 _a, uint256 _b, uint256 _c, uint256 _d, uint256 _e) internal pure returns (uint256[] r) {
                  r = new uint256[](5);
                  r[0] = _a;
                  r[1] = _b;
                  r[2] = _c;
                  r[3] = _d;
                  r[4] = _e;
              }
          }
          
          
          contract ACLHelpers {
              function decodeParamOp(uint256 _x) internal pure returns (uint8 b) {
                  return uint8(_x >> (8 * 30));
              }
          
              function decodeParamId(uint256 _x) internal pure returns (uint8 b) {
                  return uint8(_x >> (8 * 31));
              }
          
              function decodeParamsList(uint256 _x) internal pure returns (uint32 a, uint32 b, uint32 c) {
                  a = uint32(_x);
                  b = uint32(_x >> (8 * 4));
                  c = uint32(_x >> (8 * 8));
              }
          }
          
          // File: @aragon/os/contracts/common/Uint256Helpers.sol
          
          pragma solidity ^0.4.24;
          
          
          library Uint256Helpers {
              uint256 private constant MAX_UINT64 = uint64(-1);
          
              string private constant ERROR_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG";
          
              function toUint64(uint256 a) internal pure returns (uint64) {
                  require(a <= MAX_UINT64, ERROR_NUMBER_TOO_BIG);
                  return uint64(a);
              }
          }
          
          // File: @aragon/os/contracts/common/TimeHelpers.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract TimeHelpers {
              using Uint256Helpers for uint256;
          
              /**
              * @dev Returns the current block number.
              *      Using a function rather than `block.number` allows us to easily mock the block number in
              *      tests.
              */
              function getBlockNumber() internal view returns (uint256) {
                  return block.number;
              }
          
              /**
              * @dev Returns the current block number, converted to uint64.
              *      Using a function rather than `block.number` allows us to easily mock the block number in
              *      tests.
              */
              function getBlockNumber64() internal view returns (uint64) {
                  return getBlockNumber().toUint64();
              }
          
              /**
              * @dev Returns the current timestamp.
              *      Using a function rather than `block.timestamp` allows us to easily mock it in
              *      tests.
              */
              function getTimestamp() internal view returns (uint256) {
                  return block.timestamp; // solium-disable-line security/no-block-members
              }
          
              /**
              * @dev Returns the current timestamp, converted to uint64.
              *      Using a function rather than `block.timestamp` allows us to easily mock it in
              *      tests.
              */
              function getTimestamp64() internal view returns (uint64) {
                  return getTimestamp().toUint64();
              }
          }
          
          // File: @aragon/os/contracts/common/Initializable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          contract Initializable is TimeHelpers {
              using UnstructuredStorage for bytes32;
          
              // keccak256("aragonOS.initializable.initializationBlock")
              bytes32 internal constant INITIALIZATION_BLOCK_POSITION = 0xebb05b386a8d34882b8711d156f463690983dc47815980fb82aeeff1aa43579e;
          
              string private constant ERROR_ALREADY_INITIALIZED = "INIT_ALREADY_INITIALIZED";
              string private constant ERROR_NOT_INITIALIZED = "INIT_NOT_INITIALIZED";
          
              modifier onlyInit {
                  require(getInitializationBlock() == 0, ERROR_ALREADY_INITIALIZED);
                  _;
              }
          
              modifier isInitialized {
                  require(hasInitialized(), ERROR_NOT_INITIALIZED);
                  _;
              }
          
              /**
              * @return Block number in which the contract was initialized
              */
              function getInitializationBlock() public view returns (uint256) {
                  return INITIALIZATION_BLOCK_POSITION.getStorageUint256();
              }
          
              /**
              * @return Whether the contract has been initialized by the time of the current block
              */
              function hasInitialized() public view returns (bool) {
                  uint256 initializationBlock = getInitializationBlock();
                  return initializationBlock != 0 && getBlockNumber() >= initializationBlock;
              }
          
              /**
              * @dev Function to be called by top level contract after initialization has finished.
              */
              function initialized() internal onlyInit {
                  INITIALIZATION_BLOCK_POSITION.setStorageUint256(getBlockNumber());
              }
          
              /**
              * @dev Function to be called by top level contract after initialization to enable the contract
              *      at a future block number rather than immediately.
              */
              function initializedAt(uint256 _blockNumber) internal onlyInit {
                  INITIALIZATION_BLOCK_POSITION.setStorageUint256(_blockNumber);
              }
          }
          
          // File: @aragon/os/contracts/common/Petrifiable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract Petrifiable is Initializable {
              // Use block UINT256_MAX (which should be never) as the initializable date
              uint256 internal constant PETRIFIED_BLOCK = uint256(-1);
          
              function isPetrified() public view returns (bool) {
                  return getInitializationBlock() == PETRIFIED_BLOCK;
              }
          
              /**
              * @dev Function to be called by top level contract to prevent being initialized.
              *      Useful for freezing base contracts when they're used behind proxies.
              */
              function petrify() internal onlyInit {
                  initializedAt(PETRIFIED_BLOCK);
              }
          }
          
          // File: @aragon/os/contracts/common/Autopetrified.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract Autopetrified is Petrifiable {
              constructor() public {
                  // Immediately petrify base (non-proxy) instances of inherited contracts on deploy.
                  // This renders them uninitializable (and unusable without a proxy).
                  petrify();
              }
          }
          
          // File: @aragon/os/contracts/common/ConversionHelpers.sol
          
          pragma solidity ^0.4.24;
          
          
          library ConversionHelpers {
              string private constant ERROR_IMPROPER_LENGTH = "CONVERSION_IMPROPER_LENGTH";
          
              function dangerouslyCastUintArrayToBytes(uint256[] memory _input) internal pure returns (bytes memory output) {
                  // Force cast the uint256[] into a bytes array, by overwriting its length
                  // Note that the bytes array doesn't need to be initialized as we immediately overwrite it
                  // with the input and a new length. The input becomes invalid from this point forward.
                  uint256 byteLength = _input.length * 32;
                  assembly {
                      output := _input
                      mstore(output, byteLength)
                  }
              }
          
              function dangerouslyCastBytesToUintArray(bytes memory _input) internal pure returns (uint256[] memory output) {
                  // Force cast the bytes array into a uint256[], by overwriting its length
                  // Note that the uint256[] doesn't need to be initialized as we immediately overwrite it
                  // with the input and a new length. The input becomes invalid from this point forward.
                  uint256 intsLength = _input.length / 32;
                  require(_input.length == intsLength * 32, ERROR_IMPROPER_LENGTH);
          
                  assembly {
                      output := _input
                      mstore(output, intsLength)
                  }
              }
          }
          
          // File: @aragon/os/contracts/common/ReentrancyGuard.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract ReentrancyGuard {
              using UnstructuredStorage for bytes32;
          
              /* Hardcoded constants to save gas
              bytes32 internal constant REENTRANCY_MUTEX_POSITION = keccak256("aragonOS.reentrancyGuard.mutex");
              */
              bytes32 private constant REENTRANCY_MUTEX_POSITION = 0xe855346402235fdd185c890e68d2c4ecad599b88587635ee285bce2fda58dacb;
          
              string private constant ERROR_REENTRANT = "REENTRANCY_REENTRANT_CALL";
          
              modifier nonReentrant() {
                  // Ensure mutex is unlocked
                  require(!REENTRANCY_MUTEX_POSITION.getStorageBool(), ERROR_REENTRANT);
          
                  // Lock mutex before function call
                  REENTRANCY_MUTEX_POSITION.setStorageBool(true);
          
                  // Perform function call
                  _;
          
                  // Unlock mutex after function call
                  REENTRANCY_MUTEX_POSITION.setStorageBool(false);
              }
          }
          
          // File: @aragon/os/contracts/lib/token/ERC20.sol
          
          // See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/a9f910d34f0ab33a1ae5e714f69f9596a02b4d91/contracts/token/ERC20/ERC20.sol
          
          pragma solidity ^0.4.24;
          
          
          /**
           * @title ERC20 interface
           * @dev see https://github.com/ethereum/EIPs/issues/20
           */
          contract ERC20 {
              function totalSupply() public view returns (uint256);
          
              function balanceOf(address _who) public view returns (uint256);
          
              function allowance(address _owner, address _spender)
                  public view returns (uint256);
          
              function transfer(address _to, uint256 _value) public returns (bool);
          
              function approve(address _spender, uint256 _value)
                  public returns (bool);
          
              function transferFrom(address _from, address _to, uint256 _value)
                  public returns (bool);
          
              event Transfer(
                  address indexed from,
                  address indexed to,
                  uint256 value
              );
          
              event Approval(
                  address indexed owner,
                  address indexed spender,
                  uint256 value
              );
          }
          
          // File: @aragon/os/contracts/common/EtherTokenConstant.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          // aragonOS and aragon-apps rely on address(0) to denote native ETH, in
          // contracts where both tokens and ETH are accepted
          contract EtherTokenConstant {
              address internal constant ETH = address(0);
          }
          
          // File: @aragon/os/contracts/common/IsContract.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract IsContract {
              /*
              * NOTE: this should NEVER be used for authentication
              * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize).
              *
              * This is only intended to be used as a sanity check that an address is actually a contract,
              * RATHER THAN an address not being a contract.
              */
              function isContract(address _target) internal view returns (bool) {
                  if (_target == address(0)) {
                      return false;
                  }
          
                  uint256 size;
                  assembly { size := extcodesize(_target) }
                  return size > 0;
              }
          }
          
          // File: @aragon/os/contracts/common/SafeERC20.sol
          
          // Inspired by AdEx (https://github.com/AdExNetwork/adex-protocol-eth/blob/b9df617829661a7518ee10f4cb6c4108659dd6d5/contracts/libs/SafeERC20.sol)
          // and 0x (https://github.com/0xProject/0x-monorepo/blob/737d1dc54d72872e24abce5a1dbe1b66d35fa21a/contracts/protocol/contracts/protocol/AssetProxy/ERC20Proxy.sol#L143)
          
          pragma solidity ^0.4.24;
          
          
          
          library SafeERC20 {
              // Before 0.5, solidity has a mismatch between `address.transfer()` and `token.transfer()`:
              // https://github.com/ethereum/solidity/issues/3544
              bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb;
          
              string private constant ERROR_TOKEN_BALANCE_REVERTED = "SAFE_ERC_20_BALANCE_REVERTED";
              string private constant ERROR_TOKEN_ALLOWANCE_REVERTED = "SAFE_ERC_20_ALLOWANCE_REVERTED";
          
              function invokeAndCheckSuccess(address _addr, bytes memory _calldata)
                  private
                  returns (bool)
              {
                  bool ret;
                  assembly {
                      let ptr := mload(0x40)    // free memory pointer
          
                      let success := call(
                          gas,                  // forward all gas
                          _addr,                // address
                          0,                    // no value
                          add(_calldata, 0x20), // calldata start
                          mload(_calldata),     // calldata length
                          ptr,                  // write output over free memory
                          0x20                  // uint256 return
                      )
          
                      if gt(success, 0) {
                          // Check number of bytes returned from last function call
                          switch returndatasize
          
                          // No bytes returned: assume success
                          case 0 {
                              ret := 1
                          }
          
                          // 32 bytes returned: check if non-zero
                          case 0x20 {
                              // Only return success if returned data was true
                              // Already have output in ptr
                              ret := eq(mload(ptr), 1)
                          }
          
                          // Not sure what was returned: don't mark as success
                          default { }
                      }
                  }
                  return ret;
              }
          
              function staticInvoke(address _addr, bytes memory _calldata)
                  private
                  view
                  returns (bool, uint256)
              {
                  bool success;
                  uint256 ret;
                  assembly {
                      let ptr := mload(0x40)    // free memory pointer
          
                      success := staticcall(
                          gas,                  // forward all gas
                          _addr,                // address
                          add(_calldata, 0x20), // calldata start
                          mload(_calldata),     // calldata length
                          ptr,                  // write output over free memory
                          0x20                  // uint256 return
                      )
          
                      if gt(success, 0) {
                          ret := mload(ptr)
                      }
                  }
                  return (success, ret);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) {
                  bytes memory transferCallData = abi.encodeWithSelector(
                      TRANSFER_SELECTOR,
                      _to,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, transferCallData);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) {
                  bytes memory transferFromCallData = abi.encodeWithSelector(
                      _token.transferFrom.selector,
                      _from,
                      _to,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, transferFromCallData);
              }
          
              /**
              * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false).
              *      Note that this makes an external call to the token.
              */
              function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) {
                  bytes memory approveCallData = abi.encodeWithSelector(
                      _token.approve.selector,
                      _spender,
                      _amount
                  );
                  return invokeAndCheckSuccess(_token, approveCallData);
              }
          
              /**
              * @dev Static call into ERC20.balanceOf().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticBalanceOf(ERC20 _token, address _owner) internal view returns (uint256) {
                  bytes memory balanceOfCallData = abi.encodeWithSelector(
                      _token.balanceOf.selector,
                      _owner
                  );
          
                  (bool success, uint256 tokenBalance) = staticInvoke(_token, balanceOfCallData);
                  require(success, ERROR_TOKEN_BALANCE_REVERTED);
          
                  return tokenBalance;
              }
          
              /**
              * @dev Static call into ERC20.allowance().
              * Reverts if the call fails for some reason (should never fail).
              */
              function staticAllowance(ERC20 _token, address _owner, address _spender) internal view returns (uint256) {
                  bytes memory allowanceCallData = abi.encodeWithSelector(
                      _token.allowance.selector,
                      _owner,
                      _spender
                  );
          
                  (bool success, uint256 allowance) = staticInvoke(_token, allowanceCallData);
                  require(success, ERROR_TOKEN_ALLOWANCE_REVERTED);
          
                  return allowance;
              }
          }
          
          // File: @aragon/os/contracts/common/VaultRecoverable.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          
          
          
          contract VaultRecoverable is IVaultRecoverable, EtherTokenConstant, IsContract {
              using SafeERC20 for ERC20;
          
              string private constant ERROR_DISALLOWED = "RECOVER_DISALLOWED";
              string private constant ERROR_VAULT_NOT_CONTRACT = "RECOVER_VAULT_NOT_CONTRACT";
              string private constant ERROR_TOKEN_TRANSFER_FAILED = "RECOVER_TOKEN_TRANSFER_FAILED";
          
              /**
               * @notice Send funds to recovery Vault. This contract should never receive funds,
               *         but in case it does, this function allows one to recover them.
               * @param _token Token balance to be sent to recovery vault.
               */
              function transferToVault(address _token) external {
                  require(allowRecoverability(_token), ERROR_DISALLOWED);
                  address vault = getRecoveryVault();
                  require(isContract(vault), ERROR_VAULT_NOT_CONTRACT);
          
                  uint256 balance;
                  if (_token == ETH) {
                      balance = address(this).balance;
                      vault.transfer(balance);
                  } else {
                      ERC20 token = ERC20(_token);
                      balance = token.staticBalanceOf(this);
                      require(token.safeTransfer(vault, balance), ERROR_TOKEN_TRANSFER_FAILED);
                  }
          
                  emit RecoverToVault(vault, _token, balance);
              }
          
              /**
              * @dev By default deriving from AragonApp makes it recoverable
              * @param token Token address that would be recovered
              * @return bool whether the app allows the recovery
              */
              function allowRecoverability(address token) public view returns (bool) {
                  return true;
              }
          
              // Cast non-implemented interface to be public so we can use it internally
              function getRecoveryVault() public view returns (address);
          }
          
          // File: @aragon/os/contracts/evmscript/IEVMScriptExecutor.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IEVMScriptExecutor {
              function execScript(bytes script, bytes input, address[] blacklist) external returns (bytes);
              function executorType() external pure returns (bytes32);
          }
          
          // File: @aragon/os/contracts/evmscript/IEVMScriptRegistry.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          contract EVMScriptRegistryConstants {
              /* Hardcoded constants to save gas
              bytes32 internal constant EVMSCRIPT_REGISTRY_APP_ID = apmNamehash("evmreg");
              */
              bytes32 internal constant EVMSCRIPT_REGISTRY_APP_ID = 0xddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd61;
          }
          
          
          interface IEVMScriptRegistry {
              function addScriptExecutor(IEVMScriptExecutor executor) external returns (uint id);
              function disableScriptExecutor(uint256 executorId) external;
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function getScriptExecutor(bytes script) public view returns (IEVMScriptExecutor);
          }
          
          // File: @aragon/os/contracts/kernel/KernelConstants.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          contract KernelAppIds {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_APP_ID = apmNamehash("kernel");
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = apmNamehash("acl");
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = apmNamehash("vault");
              */
              bytes32 internal constant KERNEL_CORE_APP_ID = 0x3b4bf6bf3ad5000ecf0f989d5befde585c6860fea3e574a4fab4c49d1c177d9c;
              bytes32 internal constant KERNEL_DEFAULT_ACL_APP_ID = 0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a;
              bytes32 internal constant KERNEL_DEFAULT_VAULT_APP_ID = 0x7e852e0fcfce6551c13800f1e7476f982525c2b5277ba14b24339c68416336d1;
          }
          
          
          contract KernelNamespaceConstants {
              /* Hardcoded constants to save gas
              bytes32 internal constant KERNEL_CORE_NAMESPACE = keccak256("core");
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = keccak256("base");
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = keccak256("app");
              */
              bytes32 internal constant KERNEL_CORE_NAMESPACE = 0xc681a85306374a5ab27f0bbc385296a54bcd314a1948b6cf61c4ea1bc44bb9f8;
              bytes32 internal constant KERNEL_APP_BASES_NAMESPACE = 0xf1f3eb40f5bc1ad1344716ced8b8a0431d840b5783aea1fd01786bc26f35ac0f;
              bytes32 internal constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
          }
          
          // File: @aragon/os/contracts/evmscript/EVMScriptRunner.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          
          
          
          contract EVMScriptRunner is AppStorage, Initializable, EVMScriptRegistryConstants, KernelNamespaceConstants {
              string private constant ERROR_EXECUTOR_UNAVAILABLE = "EVMRUN_EXECUTOR_UNAVAILABLE";
              string private constant ERROR_PROTECTED_STATE_MODIFIED = "EVMRUN_PROTECTED_STATE_MODIFIED";
          
              /* This is manually crafted in assembly
              string private constant ERROR_EXECUTOR_INVALID_RETURN = "EVMRUN_EXECUTOR_INVALID_RETURN";
              */
          
              event ScriptResult(address indexed executor, bytes script, bytes input, bytes returnData);
          
              function getEVMScriptExecutor(bytes _script) public view returns (IEVMScriptExecutor) {
                  return IEVMScriptExecutor(getEVMScriptRegistry().getScriptExecutor(_script));
              }
          
              function getEVMScriptRegistry() public view returns (IEVMScriptRegistry) {
                  address registryAddr = kernel().getApp(KERNEL_APP_ADDR_NAMESPACE, EVMSCRIPT_REGISTRY_APP_ID);
                  return IEVMScriptRegistry(registryAddr);
              }
          
              function runScript(bytes _script, bytes _input, address[] _blacklist)
                  internal
                  isInitialized
                  protectState
                  returns (bytes)
              {
                  IEVMScriptExecutor executor = getEVMScriptExecutor(_script);
                  require(address(executor) != address(0), ERROR_EXECUTOR_UNAVAILABLE);
          
                  bytes4 sig = executor.execScript.selector;
                  bytes memory data = abi.encodeWithSelector(sig, _script, _input, _blacklist);
          
                  bytes memory output;
                  assembly {
                      let success := delegatecall(
                          gas,                // forward all gas
                          executor,           // address
                          add(data, 0x20),    // calldata start
                          mload(data),        // calldata length
                          0,                  // don't write output (we'll handle this ourselves)
                          0                   // don't write output
                      )
          
                      output := mload(0x40) // free mem ptr get
          
                      switch success
                      case 0 {
                          // If the call errored, forward its full error data
                          returndatacopy(output, 0, returndatasize)
                          revert(output, returndatasize)
                      }
                      default {
                          switch gt(returndatasize, 0x3f)
                          case 0 {
                              // Need at least 0x40 bytes returned for properly ABI-encoded bytes values,
                              // revert with "EVMRUN_EXECUTOR_INVALID_RETURN"
                              // See remix: doing a `revert("EVMRUN_EXECUTOR_INVALID_RETURN")` always results in
                              // this memory layout
                              mstore(output, 0x08c379a000000000000000000000000000000000000000000000000000000000)         // error identifier
                              mstore(add(output, 0x04), 0x0000000000000000000000000000000000000000000000000000000000000020) // starting offset
                              mstore(add(output, 0x24), 0x000000000000000000000000000000000000000000000000000000000000001e) // reason length
                              mstore(add(output, 0x44), 0x45564d52554e5f4558454355544f525f494e56414c49445f52455455524e0000) // reason
          
                              revert(output, 100) // 100 = 4 + 3 * 32 (error identifier + 3 words for the ABI encoded error)
                          }
                          default {
                              // Copy result
                              //
                              // Needs to perform an ABI decode for the expected `bytes` return type of
                              // `executor.execScript()` as solidity will automatically ABI encode the returned bytes as:
                              //    [ position of the first dynamic length return value = 0x20 (32 bytes) ]
                              //    [ output length (32 bytes) ]
                              //    [ output content (N bytes) ]
                              //
                              // Perform the ABI decode by ignoring the first 32 bytes of the return data
                              let copysize := sub(returndatasize, 0x20)
                              returndatacopy(output, 0x20, copysize)
          
                              mstore(0x40, add(output, copysize)) // free mem ptr set
                          }
                      }
                  }
          
                  emit ScriptResult(address(executor), _script, _input, output);
          
                  return output;
              }
          
              modifier protectState {
                  address preKernel = address(kernel());
                  bytes32 preAppId = appId();
                  _; // exec
                  require(address(kernel()) == preKernel, ERROR_PROTECTED_STATE_MODIFIED);
                  require(appId() == preAppId, ERROR_PROTECTED_STATE_MODIFIED);
              }
          }
          
          // File: @aragon/os/contracts/apps/AragonApp.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          
          
          
          
          
          
          
          // Contracts inheriting from AragonApp are, by default, immediately petrified upon deployment so
          // that they can never be initialized.
          // Unless overriden, this behaviour enforces those contracts to be usable only behind an AppProxy.
          // ReentrancyGuard, EVMScriptRunner, and ACLSyntaxSugar are not directly used by this contract, but
          // are included so that they are automatically usable by subclassing contracts
          contract AragonApp is AppStorage, Autopetrified, VaultRecoverable, ReentrancyGuard, EVMScriptRunner, ACLSyntaxSugar {
              string private constant ERROR_AUTH_FAILED = "APP_AUTH_FAILED";
          
              modifier auth(bytes32 _role) {
                  require(canPerform(msg.sender, _role, new uint256[](0)), ERROR_AUTH_FAILED);
                  _;
              }
          
              modifier authP(bytes32 _role, uint256[] _params) {
                  require(canPerform(msg.sender, _role, _params), ERROR_AUTH_FAILED);
                  _;
              }
          
              /**
              * @dev Check whether an action can be performed by a sender for a particular role on this app
              * @param _sender Sender of the call
              * @param _role Role on this app
              * @param _params Permission params for the role
              * @return Boolean indicating whether the sender has the permissions to perform the action.
              *         Always returns false if the app hasn't been initialized yet.
              */
              function canPerform(address _sender, bytes32 _role, uint256[] _params) public view returns (bool) {
                  if (!hasInitialized()) {
                      return false;
                  }
          
                  IKernel linkedKernel = kernel();
                  if (address(linkedKernel) == address(0)) {
                      return false;
                  }
          
                  return linkedKernel.hasPermission(
                      _sender,
                      address(this),
                      _role,
                      ConversionHelpers.dangerouslyCastUintArrayToBytes(_params)
                  );
              }
          
              /**
              * @dev Get the recovery vault for the app
              * @return Recovery vault address for the app
              */
              function getRecoveryVault() public view returns (address) {
                  // Funds recovery via a vault is only available when used with a kernel
                  return kernel().getRecoveryVault(); // if kernel is not set, it will revert
              }
          }
          
          // File: @aragon/os/contracts/common/IForwarder.sol
          
          /*
           * SPDX-License-Identitifer:    MIT
           */
          
          pragma solidity ^0.4.24;
          
          
          interface IForwarder {
              function isForwarder() external pure returns (bool);
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function canForward(address sender, bytes evmCallScript) public view returns (bool);
          
              // TODO: this should be external
              // See https://github.com/ethereum/solidity/issues/4832
              function forward(bytes evmCallScript) public;
          }
          
          // File: @aragon/os/contracts/lib/math/SafeMath.sol
          
          // See https://github.com/OpenZeppelin/openzeppelin-solidity/blob/d51e38758e1d985661534534d5c61e27bece5042/contracts/math/SafeMath.sol
          // Adapted to use pragma ^0.4.24 and satisfy our linter rules
          
          pragma solidity ^0.4.24;
          
          
          /**
           * @title SafeMath
           * @dev Math operations with safety checks that revert on error
           */
          library SafeMath {
              string private constant ERROR_ADD_OVERFLOW = "MATH_ADD_OVERFLOW";
              string private constant ERROR_SUB_UNDERFLOW = "MATH_SUB_UNDERFLOW";
              string private constant ERROR_MUL_OVERFLOW = "MATH_MUL_OVERFLOW";
              string private constant ERROR_DIV_ZERO = "MATH_DIV_ZERO";
          
              /**
              * @dev Multiplies two numbers, reverts on 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-solidity/pull/522
                  if (_a == 0) {
                      return 0;
                  }
          
                  uint256 c = _a * _b;
                  require(c / _a == _b, ERROR_MUL_OVERFLOW);
          
                  return c;
              }
          
              /**
              * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
              */
              function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
                  require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0
                  uint256 c = _a / _b;
                  // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
          
                  return c;
              }
          
              /**
              * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
              */
              function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                  require(_b <= _a, ERROR_SUB_UNDERFLOW);
                  uint256 c = _a - _b;
          
                  return c;
              }
          
              /**
              * @dev Adds two numbers, reverts on overflow.
              */
              function add(uint256 _a, uint256 _b) internal pure returns (uint256) {
                  uint256 c = _a + _b;
                  require(c >= _a, ERROR_ADD_OVERFLOW);
          
                  return c;
              }
          
              /**
              * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
              * reverts when dividing by zero.
              */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b != 0, ERROR_DIV_ZERO);
                  return a % b;
              }
          }
          
          // File: @aragon/apps-shared-minime/contracts/ITokenController.sol
          
          pragma solidity ^0.4.24;
          
          /// @dev The token controller contract must implement these functions
          
          
          interface ITokenController {
              /// @notice Called when `_owner` sends ether to the MiniMe Token contract
              /// @param _owner The address that sent the ether to create tokens
              /// @return True if the ether is accepted, false if it throws
              function proxyPayment(address _owner) external payable returns(bool);
          
              /// @notice Notifies the controller about a token transfer allowing the
              ///  controller to react if desired
              /// @param _from The origin of the transfer
              /// @param _to The destination of the transfer
              /// @param _amount The amount of the transfer
              /// @return False if the controller does not authorize the transfer
              function onTransfer(address _from, address _to, uint _amount) external returns(bool);
          
              /// @notice Notifies the controller about an approval allowing the
              ///  controller to react if desired
              /// @param _owner The address that calls `approve()`
              /// @param _spender The spender in the `approve()` call
              /// @param _amount The amount in the `approve()` call
              /// @return False if the controller does not authorize the approval
              function onApprove(address _owner, address _spender, uint _amount) external returns(bool);
          }
          
          // File: @aragon/apps-shared-minime/contracts/MiniMeToken.sol
          
          pragma solidity ^0.4.24;
          
          /*
              Copyright 2016, Jordi Baylina
              This program is free software: you can redistribute it and/or modify
              it under the terms of the GNU General Public License as published by
              the Free Software Foundation, either version 3 of the License, or
              (at your option) any later version.
              This program is distributed in the hope that it will be useful,
              but WITHOUT ANY WARRANTY; without even the implied warranty of
              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
              GNU General Public License for more details.
              You should have received a copy of the GNU General Public License
              along with this program.  If not, see <http://www.gnu.org/licenses/>.
           */
          
          /// @title MiniMeToken Contract
          /// @author Jordi Baylina
          /// @dev This token contract's goal is to make it easy for anyone to clone this
          ///  token using the token distribution at a given block, this will allow DAO's
          ///  and DApps to upgrade their features in a decentralized manner without
          ///  affecting the original token
          /// @dev It is ERC20 compliant, but still needs to under go further testing.
          
          
          contract Controlled {
              /// @notice The address of the controller is the only address that can call
              ///  a function with this modifier
              modifier onlyController {
                  require(msg.sender == controller);
                  _;
              }
          
              address public controller;
          
              function Controlled()  public { controller = msg.sender;}
          
              /// @notice Changes the controller of the contract
              /// @param _newController The new controller of the contract
              function changeController(address _newController) onlyController  public {
                  controller = _newController;
              }
          }
          
          contract ApproveAndCallFallBack {
              function receiveApproval(
                  address from,
                  uint256 _amount,
                  address _token,
                  bytes _data
              ) public;
          }
          
          /// @dev The actual token contract, the default controller is the msg.sender
          ///  that deploys the contract, so usually this token will be deployed by a
          ///  token controller contract, which Giveth will call a "Campaign"
          contract MiniMeToken is Controlled {
          
              string public name;                //The Token's name: e.g. DigixDAO Tokens
              uint8 public decimals;             //Number of decimals of the smallest unit
              string public symbol;              //An identifier: e.g. REP
              string public version = "MMT_0.1"; //An arbitrary versioning scheme
          
          
              /// @dev `Checkpoint` is the structure that attaches a block number to a
              ///  given value, the block number attached is the one that last changed the
              ///  value
              struct Checkpoint {
          
                  // `fromBlock` is the block number that the value was generated from
                  uint128 fromBlock;
          
                  // `value` is the amount of tokens at a specific block number
                  uint128 value;
              }
          
              // `parentToken` is the Token address that was cloned to produce this token;
              //  it will be 0x0 for a token that was not cloned
              MiniMeToken public parentToken;
          
              // `parentSnapShotBlock` is the block number from the Parent Token that was
              //  used to determine the initial distribution of the Clone Token
              uint public parentSnapShotBlock;
          
              // `creationBlock` is the block number that the Clone Token was created
              uint public creationBlock;
          
              // `balances` is the map that tracks the balance of each address, in this
              //  contract when the balance changes the block number that the change
              //  occurred is also included in the map
              mapping (address => Checkpoint[]) balances;
          
              // `allowed` tracks any extra transfer rights as in all ERC20 tokens
              mapping (address => mapping (address => uint256)) allowed;
          
              // Tracks the history of the `totalSupply` of the token
              Checkpoint[] totalSupplyHistory;
          
              // Flag that determines if the token is transferable or not.
              bool public transfersEnabled;
          
              // The factory used to create new clone tokens
              MiniMeTokenFactory public tokenFactory;
          
          ////////////////
          // Constructor
          ////////////////
          
              /// @notice Constructor to create a MiniMeToken
              /// @param _tokenFactory The address of the MiniMeTokenFactory contract that
              ///  will create the Clone token contracts, the token factory needs to be
              ///  deployed first
              /// @param _parentToken Address of the parent token, set to 0x0 if it is a
              ///  new token
              /// @param _parentSnapShotBlock Block of the parent token that will
              ///  determine the initial distribution of the clone token, set to 0 if it
              ///  is a new token
              /// @param _tokenName Name of the new token
              /// @param _decimalUnits Number of decimals of the new token
              /// @param _tokenSymbol Token Symbol for the new token
              /// @param _transfersEnabled If true, tokens will be able to be transferred
              function MiniMeToken(
                  MiniMeTokenFactory _tokenFactory,
                  MiniMeToken _parentToken,
                  uint _parentSnapShotBlock,
                  string _tokenName,
                  uint8 _decimalUnits,
                  string _tokenSymbol,
                  bool _transfersEnabled
              )  public
              {
                  tokenFactory = _tokenFactory;
                  name = _tokenName;                                 // Set the name
                  decimals = _decimalUnits;                          // Set the decimals
                  symbol = _tokenSymbol;                             // Set the symbol
                  parentToken = _parentToken;
                  parentSnapShotBlock = _parentSnapShotBlock;
                  transfersEnabled = _transfersEnabled;
                  creationBlock = block.number;
              }
          
          
          ///////////////////
          // ERC20 Methods
          ///////////////////
          
              /// @notice Send `_amount` tokens to `_to` from `msg.sender`
              /// @param _to The address of the recipient
              /// @param _amount The amount of tokens to be transferred
              /// @return Whether the transfer was successful or not
              function transfer(address _to, uint256 _amount) public returns (bool success) {
                  require(transfersEnabled);
                  return doTransfer(msg.sender, _to, _amount);
              }
          
              /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
              ///  is approved by `_from`
              /// @param _from The address holding the tokens being transferred
              /// @param _to The address of the recipient
              /// @param _amount The amount of tokens to be transferred
              /// @return True if the transfer was successful
              function transferFrom(address _from, address _to, uint256 _amount) public returns (bool success) {
          
                  // The controller of this contract can move tokens around at will,
                  //  this is important to recognize! Confirm that you trust the
                  //  controller of this contract, which in most situations should be
                  //  another open source smart contract or 0x0
                  if (msg.sender != controller) {
                      require(transfersEnabled);
          
                      // The standard ERC 20 transferFrom functionality
                      if (allowed[_from][msg.sender] < _amount)
                          return false;
                      allowed[_from][msg.sender] -= _amount;
                  }
                  return doTransfer(_from, _to, _amount);
              }
          
              /// @dev This is the actual transfer function in the token contract, it can
              ///  only be called by other functions in this contract.
              /// @param _from The address holding the tokens being transferred
              /// @param _to The address of the recipient
              /// @param _amount The amount of tokens to be transferred
              /// @return True if the transfer was successful
              function doTransfer(address _from, address _to, uint _amount) internal returns(bool) {
                  if (_amount == 0) {
                      return true;
                  }
                  require(parentSnapShotBlock < block.number);
                  // Do not allow transfer to 0x0 or the token contract itself
                  require((_to != 0) && (_to != address(this)));
                  // If the amount being transfered is more than the balance of the
                  //  account the transfer returns false
                  var previousBalanceFrom = balanceOfAt(_from, block.number);
                  if (previousBalanceFrom < _amount) {
                      return false;
                  }
                  // Alerts the token controller of the transfer
                  if (isContract(controller)) {
                      // Adding the ` == true` makes the linter shut up so...
                      require(ITokenController(controller).onTransfer(_from, _to, _amount) == true);
                  }
                  // First update the balance array with the new value for the address
                  //  sending the tokens
                  updateValueAtNow(balances[_from], previousBalanceFrom - _amount);
                  // Then update the balance array with the new value for the address
                  //  receiving the tokens
                  var previousBalanceTo = balanceOfAt(_to, block.number);
                  require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
                  updateValueAtNow(balances[_to], previousBalanceTo + _amount);
                  // An event to make the transfer easy to find on the blockchain
                  Transfer(_from, _to, _amount);
                  return true;
              }
          
              /// @param _owner The address that's balance is being requested
              /// @return The balance of `_owner` at the current block
              function balanceOf(address _owner) public constant returns (uint256 balance) {
                  return balanceOfAt(_owner, block.number);
              }
          
              /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
              ///  its behalf. This is a modified version of the ERC20 approve function
              ///  to be a little bit safer
              /// @param _spender The address of the account able to transfer the tokens
              /// @param _amount The amount of tokens to be approved for transfer
              /// @return True if the approval was successful
              function approve(address _spender, uint256 _amount) public returns (bool success) {
                  require(transfersEnabled);
          
                  // To change the approve amount you first have to reduce the addresses`
                  //  allowance to zero by calling `approve(_spender,0)` if it is not
                  //  already 0 to mitigate the race condition described here:
                  //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                  require((_amount == 0) || (allowed[msg.sender][_spender] == 0));
          
                  // Alerts the token controller of the approve function call
                  if (isContract(controller)) {
                      // Adding the ` == true` makes the linter shut up so...
                      require(ITokenController(controller).onApprove(msg.sender, _spender, _amount) == true);
                  }
          
                  allowed[msg.sender][_spender] = _amount;
                  Approval(msg.sender, _spender, _amount);
                  return true;
              }
          
              /// @dev This function makes it easy to read the `allowed[]` map
              /// @param _owner The address of the account that owns the token
              /// @param _spender The address of the account able to transfer the tokens
              /// @return Amount of remaining tokens of _owner that _spender is allowed
              ///  to spend
              function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
                  return allowed[_owner][_spender];
              }
          
              /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
              ///  its behalf, and then a function is triggered in the contract that is
              ///  being approved, `_spender`. This allows users to use their tokens to
              ///  interact with contracts in one function call instead of two
              /// @param _spender The address of the contract able to transfer the tokens
              /// @param _amount The amount of tokens to be approved for transfer
              /// @return True if the function call was successful
              function approveAndCall(ApproveAndCallFallBack _spender, uint256 _amount, bytes _extraData) public returns (bool success) {
                  require(approve(_spender, _amount));
          
                  _spender.receiveApproval(
                      msg.sender,
                      _amount,
                      this,
                      _extraData
                  );
          
                  return true;
              }
          
              /// @dev This function makes it easy to get the total number of tokens
              /// @return The total number of tokens
              function totalSupply() public constant returns (uint) {
                  return totalSupplyAt(block.number);
              }
          
          
          ////////////////
          // Query balance and totalSupply in History
          ////////////////
          
              /// @dev Queries the balance of `_owner` at a specific `_blockNumber`
              /// @param _owner The address from which the balance will be retrieved
              /// @param _blockNumber The block number when the balance is queried
              /// @return The balance at `_blockNumber`
              function balanceOfAt(address _owner, uint _blockNumber) public constant returns (uint) {
          
                  // These next few lines are used when the balance of the token is
                  //  requested before a check point was ever created for this token, it
                  //  requires that the `parentToken.balanceOfAt` be queried at the
                  //  genesis block for that token as this contains initial balance of
                  //  this token
                  if ((balances[_owner].length == 0) || (balances[_owner][0].fromBlock > _blockNumber)) {
                      if (address(parentToken) != 0) {
                          return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock));
                      } else {
                          // Has no parent
                          return 0;
                      }
          
                  // This will return the expected balance during normal situations
                  } else {
                      return getValueAt(balances[_owner], _blockNumber);
                  }
              }
          
              /// @notice Total amount of tokens at a specific `_blockNumber`.
              /// @param _blockNumber The block number when the totalSupply is queried
              /// @return The total amount of tokens at `_blockNumber`
              function totalSupplyAt(uint _blockNumber) public constant returns(uint) {
          
                  // These next few lines are used when the totalSupply of the token is
                  //  requested before a check point was ever created for this token, it
                  //  requires that the `parentToken.totalSupplyAt` be queried at the
                  //  genesis block for this token as that contains totalSupply of this
                  //  token at this block number.
                  if ((totalSupplyHistory.length == 0) || (totalSupplyHistory[0].fromBlock > _blockNumber)) {
                      if (address(parentToken) != 0) {
                          return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock));
                      } else {
                          return 0;
                      }
          
                  // This will return the expected totalSupply during normal situations
                  } else {
                      return getValueAt(totalSupplyHistory, _blockNumber);
                  }
              }
          
          ////////////////
          // Clone Token Method
          ////////////////
          
              /// @notice Creates a new clone token with the initial distribution being
              ///  this token at `_snapshotBlock`
              /// @param _cloneTokenName Name of the clone token
              /// @param _cloneDecimalUnits Number of decimals of the smallest unit
              /// @param _cloneTokenSymbol Symbol of the clone token
              /// @param _snapshotBlock Block when the distribution of the parent token is
              ///  copied to set the initial distribution of the new clone token;
              ///  if the block is zero than the actual block, the current block is used
              /// @param _transfersEnabled True if transfers are allowed in the clone
              /// @return The address of the new MiniMeToken Contract
              function createCloneToken(
                  string _cloneTokenName,
                  uint8 _cloneDecimalUnits,
                  string _cloneTokenSymbol,
                  uint _snapshotBlock,
                  bool _transfersEnabled
              ) public returns(MiniMeToken)
              {
                  uint256 snapshot = _snapshotBlock == 0 ? block.number - 1 : _snapshotBlock;
          
                  MiniMeToken cloneToken = tokenFactory.createCloneToken(
                      this,
                      snapshot,
                      _cloneTokenName,
                      _cloneDecimalUnits,
                      _cloneTokenSymbol,
                      _transfersEnabled
                  );
          
                  cloneToken.changeController(msg.sender);
          
                  // An event to make the token easy to find on the blockchain
                  NewCloneToken(address(cloneToken), snapshot);
                  return cloneToken;
              }
          
          ////////////////
          // Generate and destroy tokens
          ////////////////
          
              /// @notice Generates `_amount` tokens that are assigned to `_owner`
              /// @param _owner The address that will be assigned the new tokens
              /// @param _amount The quantity of tokens generated
              /// @return True if the tokens are generated correctly
              function generateTokens(address _owner, uint _amount) onlyController public returns (bool) {
                  uint curTotalSupply = totalSupply();
                  require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow
                  uint previousBalanceTo = balanceOf(_owner);
                  require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
                  updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
                  updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
                  Transfer(0, _owner, _amount);
                  return true;
              }
          
          
              /// @notice Burns `_amount` tokens from `_owner`
              /// @param _owner The address that will lose the tokens
              /// @param _amount The quantity of tokens to burn
              /// @return True if the tokens are burned correctly
              function destroyTokens(address _owner, uint _amount) onlyController public returns (bool) {
                  uint curTotalSupply = totalSupply();
                  require(curTotalSupply >= _amount);
                  uint previousBalanceFrom = balanceOf(_owner);
                  require(previousBalanceFrom >= _amount);
                  updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
                  updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
                  Transfer(_owner, 0, _amount);
                  return true;
              }
          
          ////////////////
          // Enable tokens transfers
          ////////////////
          
          
              /// @notice Enables token holders to transfer their tokens freely if true
              /// @param _transfersEnabled True if transfers are allowed in the clone
              function enableTransfers(bool _transfersEnabled) onlyController public {
                  transfersEnabled = _transfersEnabled;
              }
          
          ////////////////
          // Internal helper functions to query and set a value in a snapshot array
          ////////////////
          
              /// @dev `getValueAt` retrieves the number of tokens at a given block number
              /// @param checkpoints The history of values being queried
              /// @param _block The block number to retrieve the value at
              /// @return The number of tokens being queried
              function getValueAt(Checkpoint[] storage checkpoints, uint _block) constant internal returns (uint) {
                  if (checkpoints.length == 0)
                      return 0;
          
                  // Shortcut for the actual value
                  if (_block >= checkpoints[checkpoints.length-1].fromBlock)
                      return checkpoints[checkpoints.length-1].value;
                  if (_block < checkpoints[0].fromBlock)
                      return 0;
          
                  // Binary search of the value in the array
                  uint min = 0;
                  uint max = checkpoints.length-1;
                  while (max > min) {
                      uint mid = (max + min + 1) / 2;
                      if (checkpoints[mid].fromBlock<=_block) {
                          min = mid;
                      } else {
                          max = mid-1;
                      }
                  }
                  return checkpoints[min].value;
              }
          
              /// @dev `updateValueAtNow` used to update the `balances` map and the
              ///  `totalSupplyHistory`
              /// @param checkpoints The history of data being updated
              /// @param _value The new number of tokens
              function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value) internal {
                  if ((checkpoints.length == 0) || (checkpoints[checkpoints.length - 1].fromBlock < block.number)) {
                      Checkpoint storage newCheckPoint = checkpoints[checkpoints.length++];
                      newCheckPoint.fromBlock = uint128(block.number);
                      newCheckPoint.value = uint128(_value);
                  } else {
                      Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length - 1];
                      oldCheckPoint.value = uint128(_value);
                  }
              }
          
              /// @dev Internal function to determine if an address is a contract
              /// @param _addr The address being queried
              /// @return True if `_addr` is a contract
              function isContract(address _addr) constant internal returns(bool) {
                  uint size;
                  if (_addr == 0)
                      return false;
          
                  assembly {
                      size := extcodesize(_addr)
                  }
          
                  return size>0;
              }
          
              /// @dev Helper function to return a min betwen the two uints
              function min(uint a, uint b) pure internal returns (uint) {
                  return a < b ? a : b;
              }
          
              /// @notice The fallback function: If the contract's controller has not been
              ///  set to 0, then the `proxyPayment` method is called which relays the
              ///  ether and creates tokens as described in the token controller contract
              function () external payable {
                  require(isContract(controller));
                  // Adding the ` == true` makes the linter shut up so...
                  require(ITokenController(controller).proxyPayment.value(msg.value)(msg.sender) == true);
              }
          
          //////////
          // Safety Methods
          //////////
          
              /// @notice This method can be used by the controller to extract mistakenly
              ///  sent tokens to this contract.
              /// @param _token The address of the token contract that you want to recover
              ///  set to 0 in case you want to extract ether.
              function claimTokens(address _token) onlyController public {
                  if (_token == 0x0) {
                      controller.transfer(this.balance);
                      return;
                  }
          
                  MiniMeToken token = MiniMeToken(_token);
                  uint balance = token.balanceOf(this);
                  token.transfer(controller, balance);
                  ClaimedTokens(_token, controller, balance);
              }
          
          ////////////////
          // Events
          ////////////////
              event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
              event Transfer(address indexed _from, address indexed _to, uint256 _amount);
              event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
              event Approval(
                  address indexed _owner,
                  address indexed _spender,
                  uint256 _amount
                  );
          
          }
          
          
          ////////////////
          // MiniMeTokenFactory
          ////////////////
          
          /// @dev This contract is used to generate clone contracts from a contract.
          ///  In solidity this is the way to create a contract from a contract of the
          ///  same class
          contract MiniMeTokenFactory {
          
              /// @notice Update the DApp by creating a new token with new functionalities
              ///  the msg.sender becomes the controller of this clone token
              /// @param _parentToken Address of the token being cloned
              /// @param _snapshotBlock Block of the parent token that will
              ///  determine the initial distribution of the clone token
              /// @param _tokenName Name of the new token
              /// @param _decimalUnits Number of decimals of the new token
              /// @param _tokenSymbol Token Symbol for the new token
              /// @param _transfersEnabled If true, tokens will be able to be transferred
              /// @return The address of the new token contract
              function createCloneToken(
                  MiniMeToken _parentToken,
                  uint _snapshotBlock,
                  string _tokenName,
                  uint8 _decimalUnits,
                  string _tokenSymbol,
                  bool _transfersEnabled
              ) public returns (MiniMeToken)
              {
                  MiniMeToken newToken = new MiniMeToken(
                      this,
                      _parentToken,
                      _snapshotBlock,
                      _tokenName,
                      _decimalUnits,
                      _tokenSymbol,
                      _transfersEnabled
                  );
          
                  newToken.changeController(msg.sender);
                  return newToken;
              }
          }
          
          // File: contracts/TokenManager.sol
          
          /*
           * SPDX-License-Identitifer:    GPL-3.0-or-later
           */
          
          /* solium-disable function-order */
          
          pragma solidity 0.4.24;
          
          
          
          
          
          
          
          contract TokenManager is ITokenController, IForwarder, AragonApp {
              using SafeMath for uint256;
          
              bytes32 public constant MINT_ROLE = keccak256("MINT_ROLE");
              bytes32 public constant ISSUE_ROLE = keccak256("ISSUE_ROLE");
              bytes32 public constant ASSIGN_ROLE = keccak256("ASSIGN_ROLE");
              bytes32 public constant REVOKE_VESTINGS_ROLE = keccak256("REVOKE_VESTINGS_ROLE");
              bytes32 public constant BURN_ROLE = keccak256("BURN_ROLE");
          
              uint256 public constant MAX_VESTINGS_PER_ADDRESS = 50;
          
              string private constant ERROR_CALLER_NOT_TOKEN = "TM_CALLER_NOT_TOKEN";
              string private constant ERROR_NO_VESTING = "TM_NO_VESTING";
              string private constant ERROR_TOKEN_CONTROLLER = "TM_TOKEN_CONTROLLER";
              string private constant ERROR_MINT_RECEIVER_IS_TM = "TM_MINT_RECEIVER_IS_TM";
              string private constant ERROR_VESTING_TO_TM = "TM_VESTING_TO_TM";
              string private constant ERROR_TOO_MANY_VESTINGS = "TM_TOO_MANY_VESTINGS";
              string private constant ERROR_WRONG_CLIFF_DATE = "TM_WRONG_CLIFF_DATE";
              string private constant ERROR_VESTING_NOT_REVOKABLE = "TM_VESTING_NOT_REVOKABLE";
              string private constant ERROR_REVOKE_TRANSFER_FROM_REVERTED = "TM_REVOKE_TRANSFER_FROM_REVERTED";
              string private constant ERROR_CAN_NOT_FORWARD = "TM_CAN_NOT_FORWARD";
              string private constant ERROR_BALANCE_INCREASE_NOT_ALLOWED = "TM_BALANCE_INC_NOT_ALLOWED";
              string private constant ERROR_ASSIGN_TRANSFER_FROM_REVERTED = "TM_ASSIGN_TRANSFER_FROM_REVERTED";
          
              struct TokenVesting {
                  uint256 amount;
                  uint64 start;
                  uint64 cliff;
                  uint64 vesting;
                  bool revokable;
              }
          
              // Note that we COMPLETELY trust this MiniMeToken to not be malicious for proper operation of this contract
              MiniMeToken public token;
              uint256 public maxAccountTokens;
          
              // We are mimicing an array in the inner mapping, we use a mapping instead to make app upgrade more graceful
              mapping (address => mapping (uint256 => TokenVesting)) internal vestings;
              mapping (address => uint256) public vestingsLengths;
          
              // Other token specific events can be watched on the token address directly (avoids duplication)
              event NewVesting(address indexed receiver, uint256 vestingId, uint256 amount);
              event RevokeVesting(address indexed receiver, uint256 vestingId, uint256 nonVestedAmount);
          
              modifier onlyToken() {
                  require(msg.sender == address(token), ERROR_CALLER_NOT_TOKEN);
                  _;
              }
          
              modifier vestingExists(address _holder, uint256 _vestingId) {
                  // TODO: it's not checking for gaps that may appear because of deletes in revokeVesting function
                  require(_vestingId < vestingsLengths[_holder], ERROR_NO_VESTING);
                  _;
              }
          
              /**
              * @notice Initialize Token Manager for `_token.symbol(): string`, whose tokens are `transferable ? 'not' : ''` transferable`_maxAccountTokens > 0 ? ' and limited to a maximum of ' + @tokenAmount(_token, _maxAccountTokens, false) + ' per account' : ''`
              * @param _token MiniMeToken address for the managed token (Token Manager instance must be already set as the token controller)
              * @param _transferable whether the token can be transferred by holders
              * @param _maxAccountTokens Maximum amount of tokens an account can have (0 for infinite tokens)
              */
              function initialize(
                  MiniMeToken _token,
                  bool _transferable,
                  uint256 _maxAccountTokens
              )
                  external
                  onlyInit
              {
                  initialized();
          
                  require(_token.controller() == address(this), ERROR_TOKEN_CONTROLLER);
          
                  token = _token;
                  maxAccountTokens = _maxAccountTokens == 0 ? uint256(-1) : _maxAccountTokens;
          
                  if (token.transfersEnabled() != _transferable) {
                      token.enableTransfers(_transferable);
                  }
              }
          
              /**
              * @notice Mint `@tokenAmount(self.token(): address, _amount, false)` tokens for `_receiver`
              * @param _receiver The address receiving the tokens, cannot be the Token Manager itself (use `issue()` instead)
              * @param _amount Number of tokens minted
              */
              function mint(address _receiver, uint256 _amount) external authP(MINT_ROLE, arr(_receiver, _amount)) {
                  require(_receiver != address(this), ERROR_MINT_RECEIVER_IS_TM);
                  _mint(_receiver, _amount);
              }
          
              /**
              * @notice Mint `@tokenAmount(self.token(): address, _amount, false)` tokens for the Token Manager
              * @param _amount Number of tokens minted
              */
              function issue(uint256 _amount) external authP(ISSUE_ROLE, arr(_amount)) {
                  _mint(address(this), _amount);
              }
          
              /**
              * @notice Assign `@tokenAmount(self.token(): address, _amount, false)` tokens to `_receiver` from the Token Manager's holdings
              * @param _receiver The address receiving the tokens
              * @param _amount Number of tokens transferred
              */
              function assign(address _receiver, uint256 _amount) external authP(ASSIGN_ROLE, arr(_receiver, _amount)) {
                  _assign(_receiver, _amount);
              }
          
              /**
              * @notice Burn `@tokenAmount(self.token(): address, _amount, false)` tokens from `_holder`
              * @param _holder Holder of tokens being burned
              * @param _amount Number of tokens being burned
              */
              function burn(address _holder, uint256 _amount) external authP(BURN_ROLE, arr(_holder, _amount)) {
                  // minime.destroyTokens() never returns false, only reverts on failure
                  token.destroyTokens(_holder, _amount);
              }
          
              /**
              * @notice Assign `@tokenAmount(self.token(): address, _amount, false)` tokens to `_receiver` from the Token Manager's holdings with a `_revokable : 'revokable' : ''` vesting starting at `@formatDate(_start)`, cliff at `@formatDate(_cliff)` (first portion of tokens transferable), and completed vesting at `@formatDate(_vested)` (all tokens transferable)
              * @param _receiver The address receiving the tokens, cannot be Token Manager itself
              * @param _amount Number of tokens vested
              * @param _start Date the vesting calculations start
              * @param _cliff Date when the initial portion of tokens are transferable
              * @param _vested Date when all tokens are transferable
              * @param _revokable Whether the vesting can be revoked by the Token Manager
              */
              function assignVested(
                  address _receiver,
                  uint256 _amount,
                  uint64 _start,
                  uint64 _cliff,
                  uint64 _vested,
                  bool _revokable
              )
                  external
                  authP(ASSIGN_ROLE, arr(_receiver, _amount))
                  returns (uint256)
              {
                  require(_receiver != address(this), ERROR_VESTING_TO_TM);
                  require(vestingsLengths[_receiver] < MAX_VESTINGS_PER_ADDRESS, ERROR_TOO_MANY_VESTINGS);
                  require(_start <= _cliff && _cliff <= _vested, ERROR_WRONG_CLIFF_DATE);
          
                  uint256 vestingId = vestingsLengths[_receiver]++;
                  vestings[_receiver][vestingId] = TokenVesting(
                      _amount,
                      _start,
                      _cliff,
                      _vested,
                      _revokable
                  );
          
                  _assign(_receiver, _amount);
          
                  emit NewVesting(_receiver, vestingId, _amount);
          
                  return vestingId;
              }
          
              /**
              * @notice Revoke vesting #`_vestingId` from `_holder`, returning unvested tokens to the Token Manager
              * @param _holder Address whose vesting to revoke
              * @param _vestingId Numeric id of the vesting
              */
              function revokeVesting(address _holder, uint256 _vestingId)
                  external
                  authP(REVOKE_VESTINGS_ROLE, arr(_holder))
                  vestingExists(_holder, _vestingId)
              {
                  TokenVesting storage v = vestings[_holder][_vestingId];
                  require(v.revokable, ERROR_VESTING_NOT_REVOKABLE);
          
                  uint256 nonVested = _calculateNonVestedTokens(
                      v.amount,
                      getTimestamp(),
                      v.start,
                      v.cliff,
                      v.vesting
                  );
          
                  // To make vestingIds immutable over time, we just zero out the revoked vesting
                  // Clearing this out also allows the token transfer back to the Token Manager to succeed
                  delete vestings[_holder][_vestingId];
          
                  // transferFrom always works as controller
                  // onTransfer hook always allows if transfering to token controller
                  require(token.transferFrom(_holder, address(this), nonVested), ERROR_REVOKE_TRANSFER_FROM_REVERTED);
          
                  emit RevokeVesting(_holder, _vestingId, nonVested);
              }
          
              // ITokenController fns
              // `onTransfer()`, `onApprove()`, and `proxyPayment()` are callbacks from the MiniMe token
              // contract and are only meant to be called through the managed MiniMe token that gets assigned
              // during initialization.
          
              /*
              * @dev Notifies the controller about a token transfer allowing the controller to decide whether
              *      to allow it or react if desired (only callable from the token).
              *      Initialization check is implicitly provided by `onlyToken()`.
              * @param _from The origin of the transfer
              * @param _to The destination of the transfer
              * @param _amount The amount of the transfer
              * @return False if the controller does not authorize the transfer
              */
              function onTransfer(address _from, address _to, uint256 _amount) external onlyToken returns (bool) {
                  return _isBalanceIncreaseAllowed(_to, _amount) && _transferableBalance(_from, getTimestamp()) >= _amount;
              }
          
              /**
              * @dev Notifies the controller about an approval allowing the controller to react if desired
              *      Initialization check is implicitly provided by `onlyToken()`.
              * @return False if the controller does not authorize the approval
              */
              function onApprove(address, address, uint) external onlyToken returns (bool) {
                  return true;
              }
          
              /**
              * @dev Called when ether is sent to the MiniMe Token contract
              *      Initialization check is implicitly provided by `onlyToken()`.
              * @return True if the ether is accepted, false for it to throw
              */
              function proxyPayment(address) external payable onlyToken returns (bool) {
                  return false;
              }
          
              // Forwarding fns
          
              function isForwarder() external pure returns (bool) {
                  return true;
              }
          
              /**
              * @notice Execute desired action as a token holder
              * @dev IForwarder interface conformance. Forwards any token holder action.
              * @param _evmScript Script being executed
              */
              function forward(bytes _evmScript) public {
                  require(canForward(msg.sender, _evmScript), ERROR_CAN_NOT_FORWARD);
                  bytes memory input = new bytes(0); // TODO: Consider input for this
          
                  // Add the managed token to the blacklist to disallow a token holder from executing actions
                  // on the token controller's (this contract) behalf
                  address[] memory blacklist = new address[](1);
                  blacklist[0] = address(token);
          
                  runScript(_evmScript, input, blacklist);
              }
          
              function canForward(address _sender, bytes) public view returns (bool) {
                  return hasInitialized() && token.balanceOf(_sender) > 0;
              }
          
              // Getter fns
          
              function getVesting(
                  address _recipient,
                  uint256 _vestingId
              )
                  public
                  view
                  vestingExists(_recipient, _vestingId)
                  returns (
                      uint256 amount,
                      uint64 start,
                      uint64 cliff,
                      uint64 vesting,
                      bool revokable
                  )
              {
                  TokenVesting storage tokenVesting = vestings[_recipient][_vestingId];
                  amount = tokenVesting.amount;
                  start = tokenVesting.start;
                  cliff = tokenVesting.cliff;
                  vesting = tokenVesting.vesting;
                  revokable = tokenVesting.revokable;
              }
          
              function spendableBalanceOf(address _holder) public view isInitialized returns (uint256) {
                  return _transferableBalance(_holder, getTimestamp());
              }
          
              function transferableBalance(address _holder, uint256 _time) public view isInitialized returns (uint256) {
                  return _transferableBalance(_holder, _time);
              }
          
              /**
              * @dev Disable recovery escape hatch for own token,
              *      as the it has the concept of issuing tokens without assigning them
              */
              function allowRecoverability(address _token) public view returns (bool) {
                  return _token != address(token);
              }
          
              // Internal fns
          
              function _assign(address _receiver, uint256 _amount) internal {
                  require(_isBalanceIncreaseAllowed(_receiver, _amount), ERROR_BALANCE_INCREASE_NOT_ALLOWED);
                  // Must use transferFrom() as transfer() does not give the token controller full control
                  require(token.transferFrom(address(this), _receiver, _amount), ERROR_ASSIGN_TRANSFER_FROM_REVERTED);
              }
          
              function _mint(address _receiver, uint256 _amount) internal {
                  require(_isBalanceIncreaseAllowed(_receiver, _amount), ERROR_BALANCE_INCREASE_NOT_ALLOWED);
                  token.generateTokens(_receiver, _amount); // minime.generateTokens() never returns false
              }
          
              function _isBalanceIncreaseAllowed(address _receiver, uint256 _inc) internal view returns (bool) {
                  // Max balance doesn't apply to the token manager itself
                  if (_receiver == address(this)) {
                      return true;
                  }
                  return token.balanceOf(_receiver).add(_inc) <= maxAccountTokens;
              }
          
              /**
              * @dev Calculate amount of non-vested tokens at a specifc time
              * @param tokens The total amount of tokens vested
              * @param time The time at which to check
              * @param start The date vesting started
              * @param cliff The cliff period
              * @param vested The fully vested date
              * @return The amount of non-vested tokens of a specific grant
              *  transferableTokens
              *   |                         _/--------   vestedTokens rect
              *   |                       _/
              *   |                     _/
              *   |                   _/
              *   |                 _/
              *   |                /
              *   |              .|
              *   |            .  |
              *   |          .    |
              *   |        .      |
              *   |      .        |
              *   |    .          |
              *   +===+===========+---------+----------> time
              *      Start       Cliff    Vested
              */
              function _calculateNonVestedTokens(
                  uint256 tokens,
                  uint256 time,
                  uint256 start,
                  uint256 cliff,
                  uint256 vested
              )
                  private
                  pure
                  returns (uint256)
              {
                  // Shortcuts for before cliff and after vested cases.
                  if (time >= vested) {
                      return 0;
                  }
                  if (time < cliff) {
                      return tokens;
                  }
          
                  // Interpolate all vested tokens.
                  // As before cliff the shortcut returns 0, we can just calculate a value
                  // in the vesting rect (as shown in above's figure)
          
                  // vestedTokens = tokens * (time - start) / (vested - start)
                  // In assignVesting we enforce start <= cliff <= vested
                  // Here we shortcut time >= vested and time < cliff,
                  // so no division by 0 is possible
                  uint256 vestedTokens = tokens.mul(time.sub(start)) / vested.sub(start);
          
                  // tokens - vestedTokens
                  return tokens.sub(vestedTokens);
              }
          
              function _transferableBalance(address _holder, uint256 _time) internal view returns (uint256) {
                  uint256 transferable = token.balanceOf(_holder);
          
                  // This check is not strictly necessary for the current version of this contract, as
                  // Token Managers now cannot assign vestings to themselves.
                  // However, this was a possibility in the past, so in case there were vestings assigned to
                  // themselves, this will still return the correct value (entire balance, as the Token
                  // Manager does not have a spending limit on its own balance).
                  if (_holder != address(this)) {
                      uint256 vestingsCount = vestingsLengths[_holder];
                      for (uint256 i = 0; i < vestingsCount; i++) {
                          TokenVesting storage v = vestings[_holder][i];
                          uint256 nonTransferable = _calculateNonVestedTokens(
                              v.amount,
                              _time,
                              v.start,
                              v.cliff,
                              v.vesting
                          );
                          transferable = transferable.sub(nonTransferable);
                      }
                  }
          
                  return transferable;
              }
          }