Contract Overview
Balance: 0 Ether
Ether Value: $0
Transactions: 1 txn
Misc:
Address Watch: Add To Watch List
Contract Creator: 0xa544f214d900969a850e57f85fc37c91a160db91at txn 0x56b1c5cbd6ae0b56e6d4e2e479ef811e401e391e76db4c38de233c508008d014
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
View All
ParentTxHash Block Age From To Value
Contract Source Code Verified (Exact Match)
Contract Name: Subscription
Compiler Text: v0.4.25+commit.59dbf8f1
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.4.24;

/*
  Super Simple Token Subscriptions - https://tokensubscription.com

  //// Breakin’ Through @ University of Wyoming ////

  Austin Thomas Griffith - https://austingriffith.com

  Building on previous works:
    https://github.com/austintgriffith/token-subscription
    https://gist.github.com/androolloyd/0a62ef48887be00a5eff5c17f2be849a
    https://media.consensys.net/subscription-services-on-the-blockchain-erc-948-6ef64b083a36
    https://medium.com/gitcoin/technical-deep-dive-architecture-choices-for-subscriptions-on-the-blockchain-erc948-5fae89cabc7a
    https://github.com/ethereum/EIPs/pull/1337
    https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1077.md
    https://github.com/gnosis/safe-contracts

  Earlier Meta Transaction Demo:
    https://github.com/austintgriffith/bouncer-proxy

  Huge thanks, as always, to OpenZeppelin for the rad contracts:
 */



/**
 * @title Elliptic curve signature operations
 * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
 * TODO Remove this library once solidity supports passing a signature to ecrecover.
 * See https://github.com/ethereum/solidity/issues/864
 */

library ECDSA {

  /**
   * @dev Recover signer address from a message by using their signature
   * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
   * @param signature bytes signature, the signature is generated using web3.eth.sign()
   */
  function recover(bytes32 hash, bytes signature)
    internal
    pure
    returns (address)
  {
    bytes32 r;
    bytes32 s;
    uint8 v;

    // Check the signature length
    if (signature.length != 65) {
      return (address(0));
    }

    // Divide the signature in r, s and v variables
    // ecrecover takes the signature parameters, and the only way to get them
    // currently is to use assembly.
    // solium-disable-next-line security/no-inline-assembly
    assembly {
      r := mload(add(signature, 32))
      s := mload(add(signature, 64))
      v := byte(0, mload(add(signature, 96)))
    }

    // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
    if (v < 27) {
      v += 27;
    }

    // If the version is correct return the signer address
    if (v != 27 && v != 28) {
      return (address(0));
    } else {
      // solium-disable-next-line arg-overflow
      return ecrecover(hash, v, r, s);
    }
  }

  /**
   * toEthSignedMessageHash
   * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
   * and hash the result
   */
  function toEthSignedMessageHash(bytes32 hash)
    internal
    pure
    returns (bytes32)
  {
    // 32 is the length in bytes of hash,
    // enforced by the type signature above
    return keccak256(
      abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
    );
  }
}



/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error
 */
library SafeMath {

  /**
  * @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);

    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); // 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);
    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);

    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);
    return a % b;
  }
}




/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
  function totalSupply() external view returns (uint256);

  function balanceOf(address who) external view returns (uint256);

  function allowance(address owner, address spender)
    external view returns (uint256);

  function transfer(address to, uint256 value) external returns (bool);

  function approve(address spender, uint256 value)
    external returns (bool);

  function transferFrom(address from, address to, uint256 value)
    external returns (bool);

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 value
  );

  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}



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

  mapping (address => uint256) private _balances;

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

  uint256 private _totalSupply;

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

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

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

  /**
  * @dev Transfer token for a specified address
  * @param to The address to transfer to.
  * @param value The amount to be transferred.
  */
  function transfer(address to, uint256 value) public returns (bool) {
    require(value <= _balances[msg.sender]);
    require(to != address(0));

    _balances[msg.sender] = _balances[msg.sender].sub(value);
    _balances[to] = _balances[to].add(value);
    emit Transfer(msg.sender, to, value);
    return true;
  }

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

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

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

    _balances[from] = _balances[from].sub(value);
    _balances[to] = _balances[to].add(value);
    _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
    emit Transfer(from, to, value);
    return true;
  }

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

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

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

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

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

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

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

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

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



contract Subscription {
    using ECDSA for bytes32;
    using SafeMath for uint256;

    //who deploys the contract
    address public author;

    // the publisher may optionally deploy requirements for the subscription
    // so only meta transactions that match the requirements can be relayed
    address public requiredToAddress;
    address public requiredTokenAddress;
    uint256 public requiredTokenAmount;
    uint256 public requiredPeriodSeconds;
    uint256 public requiredGasPrice;

    // similar to a nonce that avoids replay attacks this allows a single execution
    // every x seconds for a given subscription
    // subscriptionHash  => next valid block number
    mapping(bytes32 => uint256) public nextValidTimestamp;

    //we'll use a nonce for each from but because transactions can go through
    //multiple times, we allow anything but users can use this as a signal for
    //uniqueness
    mapping(address => uint256) public extraNonce;

    event ExecuteSubscription(
        address indexed from, //the subscriber
        address indexed to, //the publisher
        address tokenAddress, //the token address paid to the publisher
        uint256 tokenAmount, //the token amount paid to the publisher
        uint256 periodSeconds, //the period in seconds between payments
        uint256 gasPrice, //the amount of tokens to pay relayer (0 for free)
        uint256 nonce // to allow multiple subscriptions with the same parameters
    );

    constructor(
        address _toAddress,
        address _tokenAddress,
        uint256 _tokenAmount,
        uint256 _periodSeconds,
        uint256 _gasPrice
    ) public {
        requiredToAddress=_toAddress;
        requiredTokenAddress=_tokenAddress;
        requiredTokenAmount=_tokenAmount;
        requiredPeriodSeconds=_periodSeconds;
        requiredGasPrice=_gasPrice;
        author=msg.sender;
    }

    // this is used by external smart contracts to verify on-chain that a
    // particular subscription is "paid" and "active"
    // there must be a small grace period added to allow the publisher
    // or desktop miner to execute
    function isSubscriptionActive(
        bytes32 subscriptionHash,
        uint256 gracePeriodSeconds
    )
        external
        view
        returns (bool)
    {
        return (block.timestamp <=
                nextValidTimestamp[subscriptionHash].add(gracePeriodSeconds)
        );
    }

    // given the subscription details, generate a hash and try to kind of follow
    // the eip-191 standard and eip-1077 standard from my dude @avsa
    function getSubscriptionHash(
        address from, //the subscriber
        address to, //the publisher
        address tokenAddress, //the token address paid to the publisher
        uint256 tokenAmount, //the token amount paid to the publisher
        uint256 periodSeconds, //the period in seconds between payments
        uint256 gasPrice, //the amount of tokens or eth to pay relayer (0 for free)
        uint256 nonce // to allow multiple subscriptions with the same parameters
    )
        public
        view
        returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                byte(0x19),
                byte(0),
                address(this),
                from,
                to,
                tokenAddress,
                tokenAmount,
                periodSeconds,
                gasPrice,
                nonce
        ));
    }

    //ecrecover the signer from hash and the signature
    function getSubscriptionSigner(
        bytes32 subscriptionHash, //hash of subscription
        bytes signature //proof the subscriber signed the meta trasaction
    )
        public
        pure
        returns (address)
    {
        return subscriptionHash.toEthSignedMessageHash().recover(signature);
    }

    //check if a subscription is signed correctly and the timestamp is ready for
    // the next execution to happen
    function isSubscriptionReady(
        address from, //the subscriber
        address to, //the publisher
        address tokenAddress, //the token address paid to the publisher
        uint256 tokenAmount, //the token amount paid to the publisher
        uint256 periodSeconds, //the period in seconds between payments
        uint256 gasPrice, //the amount of the token to incentivize the relay network
        uint256 nonce,// to allow multiple subscriptions with the same parameters
        bytes signature //proof the subscriber signed the meta trasaction
    )
        external
        view
        returns (bool)
    {
        bytes32 subscriptionHash = getSubscriptionHash(
            from, to, tokenAddress, tokenAmount, periodSeconds, gasPrice, nonce
        );
        address signer = getSubscriptionSigner(subscriptionHash, signature);
        uint256 allowance = ERC20(tokenAddress).allowance(from, address(this));
        uint256 balance = ERC20(tokenAddress).balanceOf(from);
        return (
            signer == from &&
            from != to &&
            block.timestamp >= nextValidTimestamp[subscriptionHash] &&
            allowance >= tokenAmount.add(gasPrice) &&
            balance >= tokenAmount.add(gasPrice)
        );
    }

    // you don't really need this if you are using the approve/transferFrom method
    // because you control the flow of tokens by approving this contract address,
    // but to make the contract an extensible example for later user I'll add this
    function cancelSubscription(
        address from, //the subscriber
        address to, //the publisher
        address tokenAddress, //the token address paid to the publisher
        uint256 tokenAmount, //the token amount paid to the publisher
        uint256 periodSeconds, //the period in seconds between payments
        uint256 gasPrice, //the amount of tokens or eth to pay relayer (0 for free)
        uint256 nonce, //to allow multiple subscriptions with the same parameters
        bytes signature //proof the subscriber signed the meta trasaction
    )
        external
        returns (bool success)
    {
        bytes32 subscriptionHash = getSubscriptionHash(
            from, to, tokenAddress, tokenAmount, periodSeconds, gasPrice, nonce
        );
        address signer = getSubscriptionSigner(subscriptionHash, signature);

        //the signature must be valid
        require(signer == from, "Invalid Signature for subscription cancellation");

        //nextValidTimestamp should be a timestamp that will never
        //be reached during the brief window human existence
        nextValidTimestamp[subscriptionHash]=uint256(-1);

        return true;
    }

    // execute the transferFrom to pay the publisher from the subscriber
    // the subscriber has full control by approving this contract an allowance
    function executeSubscription(
        address from, //the subscriber
        address to, //the publisher
        address tokenAddress, //the token address paid to the publisher
        uint256 tokenAmount, //the token amount paid to the publisher
        uint256 periodSeconds, //the period in seconds between payments
        uint256 gasPrice, //the amount of tokens or eth to pay relayer (0 for free)
        uint256 nonce, // to allow multiple subscriptions with the same parameters
        bytes signature //proof the subscriber signed the meta trasaction
    )
        public
        returns (bool success)
    {
        // make sure the subscription is valid and ready
        // pulled this out so I have the hash, should be exact code as "isSubscriptionReady"
        bytes32 subscriptionHash = getSubscriptionHash(
            from, to, tokenAddress, tokenAmount, periodSeconds, gasPrice, nonce
        );
        address signer = getSubscriptionSigner(subscriptionHash, signature);

        //make sure they aren't sending to themselves
        require(to != from, "Can not send to the from address");
        //the signature must be valid
        require(signer == from, "Invalid Signature");
        //timestamp must be equal to or past the next period
        require(
            block.timestamp >= nextValidTimestamp[subscriptionHash],
            "Subscription is not ready"
        );

        // if there are requirements from the deployer, let's make sure
        // those are met exactly
        require( requiredToAddress == address(0) || to == requiredToAddress );
        require( requiredTokenAddress == address(0) || tokenAddress == requiredTokenAddress );
        require( requiredTokenAmount == 0 || tokenAmount == requiredTokenAmount );
        require( requiredPeriodSeconds == 0 || periodSeconds == requiredPeriodSeconds );
        require( requiredGasPrice == 0 || gasPrice == requiredGasPrice );

        //increment the timestamp by the period so it wont be valid until then
        nextValidTimestamp[subscriptionHash] = block.timestamp.add(periodSeconds);

        //check to see if this nonce is larger than the current count and we'll set that for this 'from'
        if(nonce > extraNonce[from]){
          extraNonce[from] = nonce;
        }

        // now, let make the transfer from the subscriber to the publisher
        ERC20(tokenAddress).transferFrom(from,to,tokenAmount);
        require(
            checkSuccess(),
            "Subscription::executeSubscription TransferFrom failed"
        );

        emit ExecuteSubscription(
            from, to, tokenAddress, tokenAmount, periodSeconds, gasPrice, nonce
        );

        // it is possible for the subscription execution to be run by a third party
        // incentivized in the terms of the subscription with a gasPrice of the tokens
        //  - pay that out now...
        if (gasPrice > 0) {
            //the relayer is incentivized by a little of the same token from
            // the subscriber ... as far as the subscriber knows, they are
            // just sending X tokens to the publisher, but the publisher can
            // choose to send Y of those X to a relayer to run their transactions
            // the publisher will receive X - Y tokens
            // this must all be setup in the constructor
            // if not, the subscriber chooses all the params including what goes
            // to the publisher and what goes to the relayer
            ERC20(tokenAddress).transferFrom(from, msg.sender, gasPrice);
            require(
                checkSuccess(),
                "Subscription::executeSubscription Failed to pay gas as from account"
            );
        }

        return true;
    }

    // because of issues with non-standard erc20s the transferFrom can always return false
    // to fix this we run it and then check the return of the previous function:
    //    https://github.com/ethereum/solidity/issues/4116
    /**
     * Checks the return value of the previous function. Returns true if the previous function
     * function returned 32 non-zero bytes or returned zero bytes.
     */
    function checkSuccess(
    )
        private
        pure
        returns (bool)
    {
        uint256 returnValue = 0;

        /* solium-disable-next-line security/no-inline-assembly */
        assembly {
            // check number of bytes returned from last function call
            switch returndatasize

            // no bytes returned: assume success
            case 0x0 {
                returnValue := 1
            }

            // 32 bytes returned: check if non-zero
            case 0x20 {
                // copy 32 bytes into scratch space
                returndatacopy(0x0, 0x0, 0x20)

                // load those bytes into returnValue
                returnValue := mload(0x0)
            }

            // not sure what was returned: dont mark as success
            default { }
        }

        return returnValue != 0;
    }
}

    Contract ABI  
[{"constant":true,"inputs":[],"name":"requiredGasPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"subscriptionHash","type":"bytes32"},{"name":"signature","type":"bytes"}],"name":"getSubscriptionSigner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requiredTokenAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredToAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredPeriodSeconds","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredTokenAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenAddress","type":"address"},{"name":"tokenAmount","type":"uint256"},{"name":"periodSeconds","type":"uint256"},{"name":"gasPrice","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"signature","type":"bytes"}],"name":"cancelSubscription","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"extraNonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"author","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"subscriptionHash","type":"bytes32"},{"name":"gracePeriodSeconds","type":"uint256"}],"name":"isSubscriptionActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenAddress","type":"address"},{"name":"tokenAmount","type":"uint256"},{"name":"periodSeconds","type":"uint256"},{"name":"gasPrice","type":"uint256"},{"name":"nonce","type":"uint256"}],"name":"getSubscriptionHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenAddress","type":"address"},{"name":"tokenAmount","type":"uint256"},{"name":"periodSeconds","type":"uint256"},{"name":"gasPrice","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"signature","type":"bytes"}],"name":"executeSubscription","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenAddress","type":"address"},{"name":"tokenAmount","type":"uint256"},{"name":"periodSeconds","type":"uint256"},{"name":"gasPrice","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"signature","type":"bytes"}],"name":"isSubscriptionReady","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"nextValidTimestamp","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_toAddress","type":"address"},{"name":"_tokenAddress","type":"address"},{"name":"_tokenAmount","type":"uint256"},{"name":"_periodSeconds","type":"uint256"},{"name":"_gasPrice","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"tokenAddress","type":"address"},{"indexed":false,"name":"tokenAmount","type":"uint256"},{"indexed":false,"name":"periodSeconds","type":"uint256"},{"indexed":false,"name":"gasPrice","type":"uint256"},{"indexed":false,"name":"nonce","type":"uint256"}],"name":"ExecuteSubscription","type":"event"}]

  Contract Creation Code Switch To Opcodes View
608060405234801561001057600080fd5b5060405160a0806110158339810160409081528151602083015191830151606084015160809094015160018054600160a060020a03948516600160a060020a0319918216179091556002805494909516938116939093179093556003556004929092556005556000805490911633179055610f85806100906000396000f3006080604052600436106100b65763ffffffff60e060020a60003504166310d9206081146100bb57806318f321a3146100e257806329d428ca1461015c578063384c3335146101715780636b40bba1146101865780636f264b2e1461019b57806371d22d4d146101b0578063a3d53d181461020e578063a6c3e6b91461022f578063ae702ba414610244578063c81478651461025f578063d3c576cd14610298578063d933c0661461031d578063ff59bff814610367575b600080fd5b3480156100c757600080fd5b506100d061037f565b60408051918252519081900360200190f35b3480156100ee57600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526101409583359536956044949193909101919081908401838280828437509497506103859650505050505050565b60408051600160a060020a039092168252519081900360200190f35b34801561016857600080fd5b506100d06103a7565b34801561017d57600080fd5b506101406103ad565b34801561019257600080fd5b506100d06103bc565b3480156101a757600080fd5b506101406103c2565b3480156101bc57600080fd5b506101fa60048035600160a060020a0390811691602480358316926044351691606435916084359160a4359160c4359160e4359182019101356103d1565b604080519115158252519081900360200190f35b34801561021a57600080fd5b506100d0600160a060020a03600435166104d0565b34801561023b57600080fd5b506101406104e2565b34801561025057600080fd5b506101fa6004356024356104f1565b34801561026b57600080fd5b506100d0600160a060020a036004358116906024358116906044351660643560843560a43560c43561051a565b3480156102a457600080fd5b50604080516020600460e43581810135601f81018490048402850184019095528484526101fa948235600160a060020a03908116956024803583169660443590931695606435956084359560a4359560c43595369561010494919391019181908401838280828437509497506106219650505050505050565b34801561032957600080fd5b506101fa60048035600160a060020a0390811691602480358316926044351691606435916084359160a4359160c4359160e435918201910135610b63565b34801561037357600080fd5b506100d0600435610d82565b60055481565b60006103a08261039485610d94565b9063ffffffff610e3e16565b9392505050565b60035481565b600154600160a060020a031681565b60045481565b600254600160a060020a031681565b60008060006103e58c8c8c8c8c8c8c61051a565b91506104218286868080601f01602080910402602001604051908101604052809392919081815260200183838082843750610385945050505050565b9050600160a060020a03808216908d16146104ac576040805160e560020a62461bcd02815260206004820152602f60248201527f496e76616c6964205369676e617475726520666f72207375627363726970746960448201527f6f6e2063616e63656c6c6174696f6e0000000000000000000000000000000000606482015290519081900360840190fd5b50600090815260066020526040902060001990555060019998505050505050505050565b60076020526000908152604090205481565b600054600160a060020a031681565b600082815260066020526040812054610510908363ffffffff610f1316565b4211159392505050565b604080517f19000000000000000000000000000000000000000000000000000000000000006020808301919091526000602183018190526c010000000000000000000000003081026022850152600160a060020a03808d1682026036860152808c168202604a8601528a1602605e840152607283018890526092830187905260b2830186905260d28084018690528451808503909101815260f29093019384905282519093918291908401908083835b602083106105e95780518252601f1990920191602091820191016105ca565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209b9a5050505050505050505050565b60008060006106358b8b8b8b8b8b8b61051a565b91506106418285610385565b9050600160a060020a038a8116908c1614156106a7576040805160e560020a62461bcd02815260206004820181905260248201527f43616e206e6f742073656e6420746f207468652066726f6d2061646472657373604482015290519081900360640190fd5b600160a060020a03818116908c161461070a576040805160e560020a62461bcd02815260206004820152601160248201527f496e76616c6964205369676e6174757265000000000000000000000000000000604482015290519081900360640190fd5b600082815260066020526040902054421015610770576040805160e560020a62461bcd02815260206004820152601960248201527f537562736372697074696f6e206973206e6f7420726561647900000000000000604482015290519081900360640190fd5b600154600160a060020a031615806107955750600154600160a060020a038b81169116145b15156107a057600080fd5b600254600160a060020a031615806107c55750600254600160a060020a038a81169116145b15156107d057600080fd5b60035415806107e0575060035488145b15156107eb57600080fd5b60045415806107fb575060045487145b151561080657600080fd5b6005541580610816575060055486145b151561082157600080fd5b610831428863ffffffff610f1316565b600083815260066020908152604080832093909355600160a060020a038e16825260079052205485111561087b57600160a060020a038b1660009081526007602052604090208590555b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038d811660048301528c81166024830152604482018b90529151918b16916323b872dd916064808201926020929091908290030181600087803b1580156108ef57600080fd5b505af1158015610903573d6000803e3d6000fd5b505050506040513d602081101561091957600080fd5b506109249050610f25565b15156109a0576040805160e560020a62461bcd02815260206004820152603560248201527f537562736372697074696f6e3a3a65786563757465537562736372697074696f60448201527f6e205472616e7366657246726f6d206661696c65640000000000000000000000606482015290519081900360840190fd5b60408051600160a060020a038b81168252602082018b90528183018a905260608201899052608082018890529151828d16928e16917f96d296c945eee0618d3cc6f435f4d59f14bcefd708eab22c3de30df20b134793919081900360a00190a36000861115610b5257604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038d81166004830152336024830152604482018990529151918b16916323b872dd916064808201926020929091908290030181600087803b158015610a7b57600080fd5b505af1158015610a8f573d6000803e3d6000fd5b505050506040513d6020811015610aa557600080fd5b50610ab09050610f25565b1515610b52576040805160e560020a62461bcd02815260206004820152604360248201527f537562736372697074696f6e3a3a65786563757465537562736372697074696f60448201527f6e204661696c656420746f20706179206761732061732066726f6d206163636f60648201527f756e740000000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b5060019a9950505050505050505050565b6000806000806000610b7a8e8e8e8e8e8e8e61051a565b9350610bb68488888080601f01602080910402602001604051908101604052809392919081815260200183838082843750610385945050505050565b92508b600160a060020a031663dd62ed3e8f306040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182600160a060020a0316600160a060020a0316815260200192505050602060405180830381600087803b158015610c2d57600080fd5b505af1158015610c41573d6000803e3d6000fd5b505050506040513d6020811015610c5757600080fd5b810190808051906020019092919050505091508b600160a060020a03166370a082318f6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015610cc557600080fd5b505af1158015610cd9573d6000803e3d6000fd5b505050506040513d6020811015610cef57600080fd5b50519050600160a060020a03838116908f16148015610d2057508c600160a060020a03168e600160a060020a031614155b8015610d3a57506000848152600660205260409020544210155b8015610d555750610d518b8a63ffffffff610f1316565b8210155b8015610d705750610d6c8b8a63ffffffff610f1316565b8110155b9e9d5050505050505050505050505050565b60066020526000908152604090205481565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c80830185905283518084039091018152605c909201928390528151600093918291908401908083835b60208310610e0c5780518252601f199092019160209182019101610ded565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b60008060008084516041141515610e585760009350610f0a565b50505060208201516040830151606084015160001a601b60ff82161015610e7d57601b015b8060ff16601b14158015610e9557508060ff16601c14155b15610ea35760009350610f0a565b60408051600080825260208083018085528a905260ff8516838501526060830187905260808301869052925160019360a0808501949193601f19840193928390039091019190865af1158015610efd573d6000803e3d6000fd5b5050506020604051035193505b50505092915050565b6000828201838110156103a057600080fd5b6000803d8015610f3c5760208114610f4557610f51565b60019150610f51565b60206000803e60005191505b5015159190505600a165627a7a723058203583cf1ee43578aa8c3415971f450968da74ea150b7843ba541dabea9a63aa84002900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000


   Swarm Source:
bzzr://3583cf1ee43578aa8c3415971f450968da74ea150b7843ba541dabea9a63aa84

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.