contract AragonApp is AppStorage, Autopetrified, VaultRecoverable, 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;
        }

        // 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 _params and a new length, and _params becomes invalid from this point forward
        bytes memory how;
        uint256 byteLength = _params.length * 32;
        assembly {
            how := _params
            mstore(how, byteLength)
        }
        return linkedKernel.hasPermission(_sender, address(this), _role, how);
    }

    /**
    * @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
    }
}
// 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.
// ACLSyntaxSugar and EVMScriptRunner are not directly used by this contract, but are included so
// that they are automatically usable by subclassing contracts
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;
    }

    // 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 _params and a new length, and _params becomes invalid from this point forward
    bytes memory how;
    uint256 byteLength = _params.length * 32;
    assembly {
        how := _params
        mstore(how, byteLength)
    }
    return linkedKernel.hasPermission(_sender, address(this), _role, how);
}

/**
 * @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.
 */