// File: /home/cashlink/stokera-token/contracts/Policy.sol



pragma solidity ^0.5.3;

import './SignatureManager.sol';

// For policy contracts, it is important that there is some check on msg.sender
// so as to avoid race windows where an attacker can replay a signature
// against the contract directly, thereby potentially producing a denial of service
interface IPolicy {
    // The caller MUST ensure that the value "action" is also part of the input
    // for the given hash value, or there will be no binding between the action
    // and the action parameters.
    function tryAuthorize(string calldata action,
                       bytes32 hash,
                       address sender,
                       bytes calldata sig)
        external
        returns (bool);

    // Asserting version of tryAuthorize
    function authorize(string calldata action,
                       bytes32 hash,
                       address sender,
                       bytes calldata sig)
        external;
}

// Sender- OR signature-based validation
contract SingleAuthorityPolicy is SignatureManager, IPolicy {
    mapping(address => bool) subjectSet;
    address public authority;
    address public newAuthority;

    function initSingleAuthorityPolicy(address _authority) internal {
        authority = _authority;
        newAuthority = address(0);
    }

    modifier onlyAuthority() {
        require(msg.sender == authority, "Called by non-authority");
        _;
    }

    function setAuthority(address _newAuthority)
        onlyAuthority
        external
    {
        newAuthority = _newAuthority;
    }

    function acceptAuthority() external {
        require(newAuthority == msg.sender);
        authority = newAuthority;
        newAuthority = address(0);
    }

    modifier validatesSignature() {
        // This check is important to avoid race conditions where an attacker
        // uses up a signature and causes a DoS by sending it to the policy contract
        // directly.
        require(subjectSet[msg.sender]);
        _;
    }

    function isSubject(address subject) public view returns (bool) {
        return subjectSet[subject];
    }

    function addSubject(address subject) public onlyAuthority {
        require(msg.sender == authority);
        subjectSet[subject] = true;
    }

    function removeSubject(address subject) public onlyAuthority {
        require(msg.sender == authority);
        subjectSet[subject] = false;
    }

    function tryAuthorize(string memory /*action*/,
                       bytes32 hash,
                       address _sender,
                       bytes memory sig)
        public
        validatesSignature
        returns (bool)
    {
        if (_sender == authority) {
            // Fast path
            return true;
        }
        return tryCheckAndUseSignatureImpl(hash, sig, authority);
    }

    function authorize(string calldata action,
                       bytes32 hash,
                       address sender,
                       bytes calldata sig)
        external
        validatesSignature
    {
        bool success = tryAuthorize(action, hash, sender, sig);
        require(success, "Unauthorized: Invalid signature");
    }

    function addSubjectWithSignature(address subject, bytes calldata sig) external {
        bytes32 hash = keccak256(abi.encode(
            "AddSubject",
            address(this),
            subject));
        checkAndUseSignatureImpl(hash, sig, authority);
        subjectSet[subject] = true;
    }

    function removeSubjectWithSignature(address subject, bytes calldata sig) external {
        bytes32 hash = keccak256(abi.encode(
            "RemoveSubject",
            address(this),
            subject));
        checkAndUseSignatureImpl(hash, sig, authority);
        subjectSet[subject] = false;
    }

    function revokeNonce(uint256 nonce) external onlyAuthority {
        revokeNonceImpl(nonce);
    }

    function revokeNonceWithSignature(uint256 nonce, bytes calldata sig) external {
        revokeNonceWithSignatureImpl(nonce, sig, authority);
    }

    function isNonceValid(uint256 nonce) external view returns (bool) {
        return isNonceValidImpl(nonce);
    }

    function isNonceUsed(uint256 nonce) external view returns (bool) {
        return isNonceUsedImpl(nonce);
    }

    function isNonceRevoked(uint256 nonce) external view returns (bool) {
        return isNonceRevokedImpl(nonce);
    }

    function () external payable { revert(); }
}

// File: /home/cashlink/stokera-token/contracts/SignatureManager.sol



pragma solidity ^0.5.3;

contract SignatureManager {
    // If this changes, the prefix string also has to change
    uint256 private constant EXTRA_LEN = 8 + 8 + 20 + 20;
    uint256 private constant PREFIX_STRING =
        // ("\x19Ethereum Signed Message:\n%d" % (EXTRA_LEN + 32)).encode('hex')
        0x19457468657265756d205369676e6564204d6573736167653a0a3838;

    uint256 private constant EC_LEN = 32 + 32 + 1;
    uint256 private constant SIG_LEN = EXTRA_LEN + EC_LEN;

    uint256 private constant SIGNATURE_VERSION = 1;

    event NonceUsed(uint256 nonce);
    event NonceRevoked(uint256 nonce);

    enum NonceStatus {
        Unused, Used, Revoked
    }
    mapping(uint256 => NonceStatus) nonceStatus;

    struct SignatureParams {
        uint128 expiresAt;
        uint128 version;
        uint256 nonce;
        uint256 dependentNonce;
        bytes32 r;
        bytes32 s;
        uint8 v;
    }

    // Adapted from
    // https://programtheblockchain.com/posts/2018/02/17/signing-and-verifying-messages-in-ethereum/
    // Also see https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v1.12.0/contracts/ECRecovery.sol
    //
    // It will take a bytestring and an offset, and extracts several values
    // from the signature at the given offset of the bytestring:
    //   * expiry date: an simple timestamp after which the signature is invalid
    //   * nonce: a unique integer value used to identify the signature
    //   * r, s, v: ECDSA signature
    //
    // Format:
    //   256 bit / 32 byte   length (Solidity "bytes" prefix)
    //    64 bit /  8 byte   expiry time
    //   160 bit / 20 byte   nonce
    //   160 bit / 20 byte   dependent nonce
    //   256 bit / 32 byte   r
    //   256 bit / 32 byte   s
    //     8 bit /  1 byte   v
    function splitSignature(bytes memory sig, uint256 offset)
        internal pure returns (SignatureParams memory params)
    {
        require(offset < sig.length && sig.length - offset >= SIG_LEN);
        uint128 expiresAt;
        uint128 version;
        uint256 nonce;
        uint256 dependentNonce;
        bytes32 r;
        bytes32 s;
        uint8 v;

        uint256 ptr;

        assembly {
            // seek to requested signature, ptr now point to 32-byte *before* the
            // current signature
            ptr := add(sig, offset)

            // 8 bytes expiry time
            ptr := add(ptr, 8)
            expiresAt := and(mload(ptr), 0xffffffffffffffff)

            // 8 bytes version
            ptr := add(ptr, 8)
            version := and(mload(ptr), 0xffffffffffffffff)

            // 20 bytes nonce
            ptr := add(ptr, 20)
            nonce := and(mload(ptr), 0xffffffffffffffffffffffffffffffffffffffff)

            // 20 bytes dependent nonce
            ptr := add(ptr, 20)
            dependentNonce := and(mload(ptr), 0xffffffffffffffffffffffffffffffffffffffff)

            // 32 bytes r
            ptr := add(ptr, 32)
            r := mload(ptr)

            // 32 bytes s
            ptr := add(ptr, 32)
            s := mload(ptr)

            // 1 byte v
            ptr := add(ptr, 32)
            v := byte(0, mload(ptr))
        }

        // web3 creates signatures with v in {0,1,2,3} instead of {27,28,29,30}
        //
        // ecrecover of course expects the latter.
        if (v < 27)
            v += 27;

        params.expiresAt = expiresAt;
        params.version = version;
        params.nonce = nonce;
        params.dependentNonce = dependentNonce;
        params.r = r;
        params.s = s;
        params.v = v;
    }

    function isNonceValidImpl(uint256 nonce) internal view returns (bool) {
        return nonceStatus[nonce] == NonceStatus.Unused;
    }

    function isNonceUsedImpl(uint256 nonce) internal view returns (bool) {
        return nonceStatus[nonce] == NonceStatus.Used;
    }

    function isNonceRevokedImpl(uint256 nonce) internal view returns (bool) {
        return nonceStatus[nonce] == NonceStatus.Revoked;
    }

    function revokeNonceImpl(uint256 nonce) internal {
        require(nonceStatus[nonce] == NonceStatus.Unused, "Nonce must be unused");
        emit NonceRevoked(nonce);
        nonceStatus[nonce] = NonceStatus.Revoked;
    }

    function makePrefixedHash(bytes32 message, bytes memory sig, uint256 offset)
        internal pure
        returns (bytes32)
    {
        uint256 extraLen = EXTRA_LEN;  // copy for inline assembly code
        uint256 prefixStr = PREFIX_STRING;  // copy for inline assembly code
        uint256 len = 28 + 32 + EXTRA_LEN;
        bytes memory preimage = new bytes(len);
        uint256 dst;
        uint256 src;
        assembly {
            // because of 32-byte size header, this points to last 32-byte word
            // of destination buffer
            dst := add(preimage, len)

            // because of 32-byte size header, this points to last 32-byte word
            // of signature params
            src := add(sig, add(offset, extraLen))

            // Copy 64 bytes (at least extraLen are needed)
            mstore(dst, mload(src))
            dst := sub(dst, 32)
            src := sub(src, 32)
            mstore(dst, mload(src))

            dst := add(preimage, 60) // 32 + 28 = size prefix + message
            mstore(dst, message)

            dst := add(preimage, 28)
            // "\x19Ethereum Signed Message:\n" ...
            mstore(dst, prefixStr)

            // Fix length field
            mstore(preimage, len)
        }
        return keccak256(preimage);
    }

    struct SignatureCheckResult {
        bool valid;
        uint256 nonce;
    }

    function isValidNonce(uint256 nonce) private view returns (bool) {
        require(nonce != 0, "nonce should never be 0");
        return nonceStatus[nonce] == NonceStatus.Unused;
    }

    function isValidDependentNonce(uint256 depNonce) private view returns (bool) {
        return depNonce == 0 || nonceStatus[depNonce] == NonceStatus.Used;
    }

    function isValidExpiryTime(uint128 expiresAt) private view returns (bool) {
        return expiresAt == 0 || expiresAt >= now;
    }

    event DebugSignatureParams(uint128 expiresAt, uint128 version,
                               uint256 nonce, uint256 dependentNonce,
                               bytes32 r, bytes32 s, uint8 v, address signedBy);

    // Verifies a signature chain
    // This should never be used outside of testing or checkAndUseSignatureImpl
    function checkSignatureChain(bytes32 message,
                                 bytes memory sig,
                                 address authority,
                                 uint256 offset,
                                 uint256 end)
        internal
        view
        returns (SignatureCheckResult memory result)
    {
        require(
            offset <= sig.length &&
            end <= sig.length &&
            offset < end &&
            (end - offset) % SIG_LEN == 0);

        bytes32 currentMessage = message;

        result.valid = false;
        result.nonce = 0;

        uint256 idx = 0;
        uint256 start = offset;
        while (offset < end) {
            SignatureParams memory params = splitSignature(sig, offset);

            address signedBy = ecrecover(makePrefixedHash(currentMessage, sig, offset),
                                         params.v, params.r, params.s);
            //emit DebugSignatureParams(params.expiresAt, params.version,
                                      //params.nonce, params.dependentNonce,
                                      //params.r, params.s, params.v,
                                      //signedBy);

            if (signedBy == address(0)
                    || !isValidExpiryTime(params.expiresAt)
                    || !isValidNonce(params.nonce)
                    || !isValidDependentNonce(params.dependentNonce)
                    || params.version != SIGNATURE_VERSION)
            {
                // Early exit because of error. The caller MUST ignore the
                // partially uninitialized nonces array
                return result;
            }

            if (offset == start) {
                // Only the first nonce (for the single non-SigningAuthority
                // signature in the chain) will be consumed
                result.nonce = params.nonce;
            }

            if (signedBy == authority) {
                result.valid = true;
                require(offset + SIG_LEN == end);
                return result;
            }

            currentMessage = keccak256(abi.encode(
                "SigningAuthority", signedBy));

            offset += SIG_LEN;
            ++idx;
        }
        require(offset == end);
    }

    event DebugHeader(uint256 header, address auth, uint256 len);
    event DebugValidSignature(uint256 offset);

    function checkSignatureImpl(bytes32 message, bytes memory sig, address authority)
        internal
        view
        returns (SignatureCheckResult memory result)
    {
        uint256 offset = 0;
        while (offset < sig.length) {
            // offset < sig.length checked just now, so LHS cannot underflow
            require(sig.length - offset >= 0x20);
            uint256 header;
            assembly {
                // skip length field and seek to offset
                header := mload(add(sig, add(0x20, offset)))
            }
            address signatureAuthority = address(header >> (256 - 160));
            uint256 len = header & 0xffffffff;

            // RHS cannot overflow due to len < 2^32
            require(sig.length - offset >= 0x20 + len);

            //emit DebugHeader(header, auth, len);
            offset += 0x20;
            if (signatureAuthority == authority) {
                result = checkSignatureChain(message, sig, authority, offset, offset + len);
                if (result.valid) {
                    //emit DebugValidSignature(offset);
                    return result;
                }
            }
            offset += len;
        }
        result.valid = false;
    }

    function consumeNonce(uint256 nonce) internal {
        require(nonce != 0, "nonce should never be 0");
        require(nonceStatus[nonce] == NonceStatus.Unused, "Nonce must be unused");
        // TODO how expensive is yielding this event?
        emit NonceUsed(nonce);
        nonceStatus[nonce] = NonceStatus.Used;
    }

    // Checks a signature and marks single-use signatures as used in case
    // of successful verification.
    function tryCheckAndUseSignatureImpl(bytes32 message, bytes memory sig,
                                         address authority)
        internal
        returns (bool)
    {
        SignatureCheckResult memory result =
            checkSignatureImpl(message, sig, authority);
        if (!result.valid) {
            return false;
        }
        require(result.nonce != 0);
        consumeNonce(result.nonce);
        return true;
    }

    function checkAndUseSignatureImpl(bytes32 message, bytes memory sig, address authority)
        internal
    {
        bool success = tryCheckAndUseSignatureImpl(message, sig, authority);
        require(success, "Invalid signature");
    }


    function revokeNonceWithSignatureImpl(uint256 nonce, bytes memory sig,
                                          address authority) internal {
        bytes32 hash = keccak256(abi.encode(
            "NonceRevocation",
            address(this),
            nonce));
        checkAndUseSignatureImpl(hash, sig, authority);
        revokeNonceImpl(nonce);
    }
}

// File: /home/cashlink/stokera-token/contracts/TokenPlatform.sol



pragma solidity ^0.5.3;

import './Policy.sol';
import './Upgradeable.sol';

interface ITokenPlatform {
    function isITokenPlatform() external pure returns (bool);
}

contract TokenPlatform is SingleAuthorityPolicy, ITokenPlatform {
    constructor(address _authority) public {
        initSingleAuthorityPolicy(_authority);
    }

    function isITokenPlatform() external pure returns (bool) {
        return true;
    }
}

// File: /home/cashlink/stokera-token/contracts/Upgradeable.sol



pragma solidity ^0.5.3;

import './Utils.sol';

interface IUpgradeProxy {
    event OwnershipTransferred(address indexed from, address indexed to);
    event ProxyPaused();
    event ProxyUnpaused();
    event ProxyStartUpgrade(address indexed oldAddress, address indexed newAddress,
                            uint256 fromVersion, uint256 toVersion);
    event ProxyFinishUpgrade(address indexed oldAddress, address indexed newAddress,
                             uint256 fromVersion, uint256 toVersion);
    event ProxyCallMigration(address indexed oldAddress, address indexed newAddress,
                             uint256 fromVersion, uint256 toVersion);
    event ProxyForceVersionBump(address indexed oldAddress, address indexed newAddress,
                                uint256 fromVersion, uint256 toVersion);
    event ProxyCancelUpgrade(address indexed oldAddress, address indexed newAddress,
                             uint256 fromVersion, uint256 toVersion);

    function proxyTransferOwnership(address _newOwner) external;
    function proxyAcceptOwnership() external;
    function proxyPause() external;
    function proxyUnpause() external;
    function proxyStartUpgrade(address newLogicContract, uint256 newVersion) external;
    function proxyFinishUpgrade() external;
    function proxyCallMigration(bytes calldata data) external;

    // Undo proxyStartUpgrade without actually upgrading. Restores the old logic
    // contract. This is only safe to execute before doing a successful call to
    // proxyCallMigration, after which it is UNSAFE. This is meant as a recovery
    // mechanism in case a migration fails.
    function proxyCancelUpgrade() external;

    // Without this function it is possible to reach an unrecoverable state:
    // Call proxyStartUpgrade with a smart contract that does not have a
    // migration function that bumps it to the given version.
    //
    // This can be recovered by calling this function before calling
    // proxyFinishUpgrade, and then initiating a new upgrade before unpause.
    //
    // This is an emergency recovery mechanism that should never be used under
    // normal circumstances.
    function proxyForceVersionBump() external;

    function version() external view returns (uint256);
    function logicContract() external view returns (address);
    function upgradingFromVersion() external view returns (uint256);
    function upgradingToVersion() external view returns (uint256);
}

// Inherited by both proxy and logic contract, to avoid storage location overlaps
// and function signature hash collisions
//
// Rules for logic contracts:
//
// * Does not depend on constructor behaviour. Instead it should have a migrate_0_to_1
//   migration function that takes the arguments that the constructor would normally
//   have. In fact we have to ensure that there is no constructor in the entire
//   inheritance chain, because none of them will be actually called for the
//   proxy contract. This is automatically ensured by the compiler for
//   non-trivial constructors in case the logic contract has no constructor itself,
//   but this does not hold for trivial constructors (i.e. those with zero
//   parameters), so we still have to be careful.
//
// * No private functions, so that we can extend by inheritance
//
// * There must be no publicly accessible self-destruct functionality, or
//   if there is, it MUST carry the "onlyViaProxy" modifier
//
// * Logic contracts MUST NOT write to any of the variables defined in
//   SharedBetweenProxyAndLogic since these are managed by the proxy contract,
//   with the exception of the "version" variable, which must only be written
//   within migrations.
//   Ideally the variables should not be inspected either, unless from within the
//   "onlyViaProxy" and "migration" wrappers. The only exception is the "owner"
//   variable, which can be re-used by the logic contract so as to avoid adding
//   a second variable with essentially the same meaning.
//
// TODO investigate if we want a way to execute stateful things as the owner
// while the contract is paused. Probably it is not needed because we can call
// proxyUnpause() -> stateful action -> proxyPause() in a transaction? We should
// test this though
contract SharedBetweenProxyAndLogic is IUpgradeProxy {
    enum ProxyState {Normal, Paused, Upgrading, CallingMigrationFunction}

    // All of these state variables are managed by the proxy and MUST NOT
    // be written by
    address public owner;
    address public newOwner;
    ProxyState public proxyState;
    // Technically, this is redundant since for example
    // isProxy == logicContract != 0 || proxyState != 0.
    // Better be a bit more explicit though.
    bool isProxy;

    uint256 public upgradingFromVersion;
    uint256 public upgradingToVersion;
    address public logicContract;
    uint256 public version;

    address internal oldLogicContract;

    modifier onlyOwner {
        require(msg.sender == owner, "Sender must be owner");
        _;
    }
}

contract ContractLogic is SharedBetweenProxyAndLogic {
    // IUpgradeProxy fake implementation to make Solidity happy. It would be better
    // to just have these calls fall through, but this is not currently possible?
    function proxyTransferOwnership(address) external { revert(); }
    function proxyAcceptOwnership() external { revert(); }
    function proxyPause() external { revert(); }
    function proxyUnpause() external { revert(); }
    function proxyStartUpgrade(address, uint256) external { revert(); }
    function proxyCancelUpgrade() external { revert(); }
    function proxyFinishUpgrade() external { revert(); }
    function proxyCallMigration(bytes calldata) external { revert(); }
    function proxyForceVersionBump() external { revert(); }

    // General recommendation is to not accept funds if not required
    // (can still be forced via self-destruction)
    function () external payable { revert(); }

    // TODO currently unused and untested
    modifier onlyViaProxy() {
        // Must be called on the proxy, not the deployed logic contract
        require(isProxy);
        _;
    }

    modifier migration(uint256 fromVersion, uint256 toVersion) {
        // This is just a sanity check, the fact that we are in CallingMigrationFunction
        // state means that this function call was performed via proxyCallMigration
        assert(msg.sender == owner);

        assert(toVersion - fromVersion == 1);

        // Must be called on the proxy in the correct state, not the deployed
        // logic contract
        require(isProxy);
        require(proxyState == ProxyState.CallingMigrationFunction);

        // Make sure the migration version range is consistent with the
        // actual upgrade version range
        require(fromVersion >= upgradingFromVersion && toVersion <= upgradingToVersion);
        require(version == fromVersion);
        uint256 oldVersion = version;
        _;
        // Migration functions should be monotone in the version, and hold their
        // promise regarding the migrated version range
        assert(version >= oldVersion);
        assert(version <= toVersion);
        // This can be used by the caller to verify that a function with this
        // modifier was used
        proxyState = ProxyState.Upgrading;
    }
}

contract UpgradeProxy is SharedBetweenProxyAndLogic {
    constructor(address _owner) public {
        owner = _owner;
        newOwner = address(0);
        proxyState = ProxyState.Paused;
        logicContract = address(0);
        oldLogicContract = address(0);
        isProxy = true;
        version = 0;
        emit ProxyPaused();
    }

    function proxyTransferOwnership(address _newOwner) external onlyOwner {
        newOwner = _newOwner;
    }

    function proxyAcceptOwnership() external {
        require(msg.sender == newOwner);
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
        newOwner = address(0);
    }

    function proxyPause() external onlyOwner {
        emit ProxyPaused();
        require(proxyState == ProxyState.Normal);
        proxyState = ProxyState.Paused;
    }

    function proxyUnpause() external onlyOwner {
        emit ProxyUnpaused();
        // Make sure the first unpause only happens after a logic contract was set
        require(Utils.isContract(logicContract));
        require(proxyState == ProxyState.Paused);
        proxyState = ProxyState.Normal;
    }

    function proxyStartUpgrade(address newLogicContract, uint256 newVersion)
        external onlyOwner
    {
        require(proxyState == ProxyState.Paused);
        require(version < newVersion);
        require(Utils.isContract(newLogicContract));

        upgradingFromVersion = version;
        upgradingToVersion = newVersion;
        oldLogicContract = logicContract;
        logicContract = newLogicContract;

        emit ProxyStartUpgrade(oldLogicContract, newLogicContract,
                               upgradingFromVersion, upgradingToVersion);
        proxyState = ProxyState.Upgrading;
    }

    function proxyCallMigration(bytes calldata data)
        external onlyOwner
    {
        require(proxyState == ProxyState.Upgrading);
        require(Utils.isContract(logicContract));

        emit ProxyCallMigration(oldLogicContract, logicContract,
                                upgradingFromVersion, upgradingToVersion);

        proxyState = ProxyState.CallingMigrationFunction;
        (bool result,) = logicContract.delegatecall(data);
        require(result);

        require(proxyState == ProxyState.Upgrading);
    }

    function proxyForceVersionBump()
        external onlyOwner
    {
        require(proxyState == ProxyState.Upgrading);
        emit ProxyForceVersionBump(oldLogicContract, logicContract,
                                   upgradingFromVersion, upgradingToVersion);
        version = upgradingToVersion;
    }

    function proxyFinishUpgrade()
        external onlyOwner
    {
        require(proxyState == ProxyState.Upgrading);
        require(version == upgradingToVersion);

        emit ProxyFinishUpgrade(oldLogicContract, logicContract,
                                upgradingFromVersion, upgradingToVersion);
        proxyState = ProxyState.Paused;

        // Clean up storage
        upgradingFromVersion = 0;
        upgradingToVersion = 0;
        oldLogicContract = address(0);
    }

    function proxyCancelUpgrade()
        external onlyOwner
    {
        require(proxyState == ProxyState.Upgrading);

        emit ProxyCancelUpgrade(oldLogicContract, logicContract,
                                upgradingFromVersion, upgradingToVersion);
        logicContract = oldLogicContract;

        // It would be safer to require(version == upgradingFromVersion), but
        // we give us a little bit of freedom here in case we really mess up badly.
        version = upgradingFromVersion;
        proxyState = ProxyState.Paused;

        // Clean up storage
        upgradingFromVersion = 0;
        upgradingToVersion = 0;
        oldLogicContract = address(0);
    }

    // from
    // https://github.com/zeppelinos/labs/blob/master/upgradeability_using_eternal_storage/contracts/Proxy.sol
    function () payable external {
        require(proxyState == ProxyState.Normal);

        // TODO check that the receiver has code
        // https://blog.trailofbits.com/2018/09/05/contract-upgrade-anti-patterns/
        // For now we don't do this for performance reasons
        //require(Utils.isContract(logicContract));
        address impl = logicContract;

        assembly {
            let ptr := mload(0x40)
            calldatacopy(ptr, 0, calldatasize)
            let result := delegatecall(gas, impl, ptr, calldatasize, 0, 0)
            let size := returndatasize
            returndatacopy(ptr, 0, size)

            switch result
            case 0 { revert(ptr, size) }
            default { return(ptr, size) }
        }
    }
}

// File: /home/cashlink/stokera-token/contracts/Utils.sol



pragma solidity ^0.5.3;

library Utils {
    function isContract(address addr) external view returns (bool) {
        if (addr == address(0)) {
            return false;
        }
        uint32 size;
        assembly { size := extcodesize(addr) }
        return (size > 0);
    }
}