Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Subscription
Compiler Version
v0.4.25+commit.59dbf8f1
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2018-09-26
*/
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 Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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
608060405234801561001057600080fd5b5060405160a0806110158339810160409081528151602083015191830151606084015160809094015160018054600160a060020a03948516600160a060020a0319918216179091556002805494909516938116939093179093556003556004929092556005556000805490911633179055610f85806100906000396000f3006080604052600436106100b65763ffffffff60e060020a60003504166310d9206081146100bb57806318f321a3146100e257806329d428ca1461015c578063384c3335146101715780636b40bba1146101865780636f264b2e1461019b57806371d22d4d146101b0578063a3d53d181461020e578063a6c3e6b91461022f578063ae702ba414610244578063c81478651461025f578063d3c576cd14610298578063d933c0661461031d578063ff59bff814610367575b600080fd5b3480156100c757600080fd5b506100d061037f565b60408051918252519081900360200190f35b3480156100ee57600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526101409583359536956044949193909101919081908401838280828437509497506103859650505050505050565b60408051600160a060020a039092168252519081900360200190f35b34801561016857600080fd5b506100d06103a7565b34801561017d57600080fd5b506101406103ad565b34801561019257600080fd5b506100d06103bc565b3480156101a757600080fd5b506101406103c2565b3480156101bc57600080fd5b506101fa60048035600160a060020a0390811691602480358316926044351691606435916084359160a4359160c4359160e4359182019101356103d1565b604080519115158252519081900360200190f35b34801561021a57600080fd5b506100d0600160a060020a03600435166104d0565b34801561023b57600080fd5b506101406104e2565b34801561025057600080fd5b506101fa6004356024356104f1565b34801561026b57600080fd5b506100d0600160a060020a036004358116906024358116906044351660643560843560a43560c43561051a565b3480156102a457600080fd5b50604080516020600460e43581810135601f81018490048402850184019095528484526101fa948235600160a060020a03908116956024803583169660443590931695606435956084359560a4359560c43595369561010494919391019181908401838280828437509497506106219650505050505050565b34801561032957600080fd5b506101fa60048035600160a060020a0390811691602480358316926044351691606435916084359160a4359160c4359160e435918201910135610b63565b34801561037357600080fd5b506100d0600435610d82565b60055481565b60006103a08261039485610d94565b9063ffffffff610e3e16565b9392505050565b60035481565b600154600160a060020a031681565b60045481565b600254600160a060020a031681565b60008060006103e58c8c8c8c8c8c8c61051a565b91506104218286868080601f01602080910402602001604051908101604052809392919081815260200183838082843750610385945050505050565b9050600160a060020a03808216908d16146104ac576040805160e560020a62461bcd02815260206004820152602f60248201527f496e76616c6964205369676e617475726520666f72207375627363726970746960448201527f6f6e2063616e63656c6c6174696f6e0000000000000000000000000000000000606482015290519081900360840190fd5b50600090815260066020526040902060001990555060019998505050505050505050565b60076020526000908152604090205481565b600054600160a060020a031681565b600082815260066020526040812054610510908363ffffffff610f1316565b4211159392505050565b604080517f19000000000000000000000000000000000000000000000000000000000000006020808301919091526000602183018190526c010000000000000000000000003081026022850152600160a060020a03808d1682026036860152808c168202604a8601528a1602605e840152607283018890526092830187905260b2830186905260d28084018690528451808503909101815260f29093019384905282519093918291908401908083835b602083106105e95780518252601f1990920191602091820191016105ca565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209b9a5050505050505050505050565b60008060006106358b8b8b8b8b8b8b61051a565b91506106418285610385565b9050600160a060020a038a8116908c1614156106a7576040805160e560020a62461bcd02815260206004820181905260248201527f43616e206e6f742073656e6420746f207468652066726f6d2061646472657373604482015290519081900360640190fd5b600160a060020a03818116908c161461070a576040805160e560020a62461bcd02815260206004820152601160248201527f496e76616c6964205369676e6174757265000000000000000000000000000000604482015290519081900360640190fd5b600082815260066020526040902054421015610770576040805160e560020a62461bcd02815260206004820152601960248201527f537562736372697074696f6e206973206e6f7420726561647900000000000000604482015290519081900360640190fd5b600154600160a060020a031615806107955750600154600160a060020a038b81169116145b15156107a057600080fd5b600254600160a060020a031615806107c55750600254600160a060020a038a81169116145b15156107d057600080fd5b60035415806107e0575060035488145b15156107eb57600080fd5b60045415806107fb575060045487145b151561080657600080fd5b6005541580610816575060055486145b151561082157600080fd5b610831428863ffffffff610f1316565b600083815260066020908152604080832093909355600160a060020a038e16825260079052205485111561087b57600160a060020a038b1660009081526007602052604090208590555b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038d811660048301528c81166024830152604482018b90529151918b16916323b872dd916064808201926020929091908290030181600087803b1580156108ef57600080fd5b505af1158015610903573d6000803e3d6000fd5b505050506040513d602081101561091957600080fd5b506109249050610f25565b15156109a0576040805160e560020a62461bcd02815260206004820152603560248201527f537562736372697074696f6e3a3a65786563757465537562736372697074696f60448201527f6e205472616e7366657246726f6d206661696c65640000000000000000000000606482015290519081900360840190fd5b60408051600160a060020a038b81168252602082018b90528183018a905260608201899052608082018890529151828d16928e16917f96d296c945eee0618d3cc6f435f4d59f14bcefd708eab22c3de30df20b134793919081900360a00190a36000861115610b5257604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038d81166004830152336024830152604482018990529151918b16916323b872dd916064808201926020929091908290030181600087803b158015610a7b57600080fd5b505af1158015610a8f573d6000803e3d6000fd5b505050506040513d6020811015610aa557600080fd5b50610ab09050610f25565b1515610b52576040805160e560020a62461bcd02815260206004820152604360248201527f537562736372697074696f6e3a3a65786563757465537562736372697074696f60448201527f6e204661696c656420746f20706179206761732061732066726f6d206163636f60648201527f756e740000000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b5060019a9950505050505050505050565b6000806000806000610b7a8e8e8e8e8e8e8e61051a565b9350610bb68488888080601f01602080910402602001604051908101604052809392919081815260200183838082843750610385945050505050565b92508b600160a060020a031663dd62ed3e8f306040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182600160a060020a0316600160a060020a0316815260200192505050602060405180830381600087803b158015610c2d57600080fd5b505af1158015610c41573d6000803e3d6000fd5b505050506040513d6020811015610c5757600080fd5b810190808051906020019092919050505091508b600160a060020a03166370a082318f6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015610cc557600080fd5b505af1158015610cd9573d6000803e3d6000fd5b505050506040513d6020811015610cef57600080fd5b50519050600160a060020a03838116908f16148015610d2057508c600160a060020a03168e600160a060020a031614155b8015610d3a57506000848152600660205260409020544210155b8015610d555750610d518b8a63ffffffff610f1316565b8210155b8015610d705750610d6c8b8a63ffffffff610f1316565b8110155b9e9d5050505050505050505050505050565b60066020526000908152604090205481565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c80830185905283518084039091018152605c909201928390528151600093918291908401908083835b60208310610e0c5780518252601f199092019160209182019101610ded565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b60008060008084516041141515610e585760009350610f0a565b50505060208201516040830151606084015160001a601b60ff82161015610e7d57601b015b8060ff16601b14158015610e9557508060ff16601c14155b15610ea35760009350610f0a565b60408051600080825260208083018085528a905260ff8516838501526060830187905260808301869052925160019360a0808501949193601f19840193928390039091019190865af1158015610efd573d6000803e3d6000fd5b5050506020604051035193505b50505092915050565b6000828201838110156103a057600080fd5b6000803d8015610f3c5760208114610f4557610f51565b60019150610f51565b60206000803e60005191505b5015159190505600a165627a7a723058203583cf1ee43578aa8c3415971f450968da74ea150b7843ba541dabea9a63aa84002900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106100b65763ffffffff60e060020a60003504166310d9206081146100bb57806318f321a3146100e257806329d428ca1461015c578063384c3335146101715780636b40bba1146101865780636f264b2e1461019b57806371d22d4d146101b0578063a3d53d181461020e578063a6c3e6b91461022f578063ae702ba414610244578063c81478651461025f578063d3c576cd14610298578063d933c0661461031d578063ff59bff814610367575b600080fd5b3480156100c757600080fd5b506100d061037f565b60408051918252519081900360200190f35b3480156100ee57600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526101409583359536956044949193909101919081908401838280828437509497506103859650505050505050565b60408051600160a060020a039092168252519081900360200190f35b34801561016857600080fd5b506100d06103a7565b34801561017d57600080fd5b506101406103ad565b34801561019257600080fd5b506100d06103bc565b3480156101a757600080fd5b506101406103c2565b3480156101bc57600080fd5b506101fa60048035600160a060020a0390811691602480358316926044351691606435916084359160a4359160c4359160e4359182019101356103d1565b604080519115158252519081900360200190f35b34801561021a57600080fd5b506100d0600160a060020a03600435166104d0565b34801561023b57600080fd5b506101406104e2565b34801561025057600080fd5b506101fa6004356024356104f1565b34801561026b57600080fd5b506100d0600160a060020a036004358116906024358116906044351660643560843560a43560c43561051a565b3480156102a457600080fd5b50604080516020600460e43581810135601f81018490048402850184019095528484526101fa948235600160a060020a03908116956024803583169660443590931695606435956084359560a4359560c43595369561010494919391019181908401838280828437509497506106219650505050505050565b34801561032957600080fd5b506101fa60048035600160a060020a0390811691602480358316926044351691606435916084359160a4359160c4359160e435918201910135610b63565b34801561037357600080fd5b506100d0600435610d82565b60055481565b60006103a08261039485610d94565b9063ffffffff610e3e16565b9392505050565b60035481565b600154600160a060020a031681565b60045481565b600254600160a060020a031681565b60008060006103e58c8c8c8c8c8c8c61051a565b91506104218286868080601f01602080910402602001604051908101604052809392919081815260200183838082843750610385945050505050565b9050600160a060020a03808216908d16146104ac576040805160e560020a62461bcd02815260206004820152602f60248201527f496e76616c6964205369676e617475726520666f72207375627363726970746960448201527f6f6e2063616e63656c6c6174696f6e0000000000000000000000000000000000606482015290519081900360840190fd5b50600090815260066020526040902060001990555060019998505050505050505050565b60076020526000908152604090205481565b600054600160a060020a031681565b600082815260066020526040812054610510908363ffffffff610f1316565b4211159392505050565b604080517f19000000000000000000000000000000000000000000000000000000000000006020808301919091526000602183018190526c010000000000000000000000003081026022850152600160a060020a03808d1682026036860152808c168202604a8601528a1602605e840152607283018890526092830187905260b2830186905260d28084018690528451808503909101815260f29093019384905282519093918291908401908083835b602083106105e95780518252601f1990920191602091820191016105ca565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209b9a5050505050505050505050565b60008060006106358b8b8b8b8b8b8b61051a565b91506106418285610385565b9050600160a060020a038a8116908c1614156106a7576040805160e560020a62461bcd02815260206004820181905260248201527f43616e206e6f742073656e6420746f207468652066726f6d2061646472657373604482015290519081900360640190fd5b600160a060020a03818116908c161461070a576040805160e560020a62461bcd02815260206004820152601160248201527f496e76616c6964205369676e6174757265000000000000000000000000000000604482015290519081900360640190fd5b600082815260066020526040902054421015610770576040805160e560020a62461bcd02815260206004820152601960248201527f537562736372697074696f6e206973206e6f7420726561647900000000000000604482015290519081900360640190fd5b600154600160a060020a031615806107955750600154600160a060020a038b81169116145b15156107a057600080fd5b600254600160a060020a031615806107c55750600254600160a060020a038a81169116145b15156107d057600080fd5b60035415806107e0575060035488145b15156107eb57600080fd5b60045415806107fb575060045487145b151561080657600080fd5b6005541580610816575060055486145b151561082157600080fd5b610831428863ffffffff610f1316565b600083815260066020908152604080832093909355600160a060020a038e16825260079052205485111561087b57600160a060020a038b1660009081526007602052604090208590555b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038d811660048301528c81166024830152604482018b90529151918b16916323b872dd916064808201926020929091908290030181600087803b1580156108ef57600080fd5b505af1158015610903573d6000803e3d6000fd5b505050506040513d602081101561091957600080fd5b506109249050610f25565b15156109a0576040805160e560020a62461bcd02815260206004820152603560248201527f537562736372697074696f6e3a3a65786563757465537562736372697074696f60448201527f6e205472616e7366657246726f6d206661696c65640000000000000000000000606482015290519081900360840190fd5b60408051600160a060020a038b81168252602082018b90528183018a905260608201899052608082018890529151828d16928e16917f96d296c945eee0618d3cc6f435f4d59f14bcefd708eab22c3de30df20b134793919081900360a00190a36000861115610b5257604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038d81166004830152336024830152604482018990529151918b16916323b872dd916064808201926020929091908290030181600087803b158015610a7b57600080fd5b505af1158015610a8f573d6000803e3d6000fd5b505050506040513d6020811015610aa557600080fd5b50610ab09050610f25565b1515610b52576040805160e560020a62461bcd02815260206004820152604360248201527f537562736372697074696f6e3a3a65786563757465537562736372697074696f60448201527f6e204661696c656420746f20706179206761732061732066726f6d206163636f60648201527f756e740000000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b5060019a9950505050505050505050565b6000806000806000610b7a8e8e8e8e8e8e8e61051a565b9350610bb68488888080601f01602080910402602001604051908101604052809392919081815260200183838082843750610385945050505050565b92508b600160a060020a031663dd62ed3e8f306040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182600160a060020a0316600160a060020a0316815260200192505050602060405180830381600087803b158015610c2d57600080fd5b505af1158015610c41573d6000803e3d6000fd5b505050506040513d6020811015610c5757600080fd5b810190808051906020019092919050505091508b600160a060020a03166370a082318f6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015610cc557600080fd5b505af1158015610cd9573d6000803e3d6000fd5b505050506040513d6020811015610cef57600080fd5b50519050600160a060020a03838116908f16148015610d2057508c600160a060020a03168e600160a060020a031614155b8015610d3a57506000848152600660205260409020544210155b8015610d555750610d518b8a63ffffffff610f1316565b8210155b8015610d705750610d6c8b8a63ffffffff610f1316565b8110155b9e9d5050505050505050505050505050565b60066020526000908152604090205481565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c80830185905283518084039091018152605c909201928390528151600093918291908401908083835b60208310610e0c5780518252601f199092019160209182019101610ded565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b60008060008084516041141515610e585760009350610f0a565b50505060208201516040830151606084015160001a601b60ff82161015610e7d57601b015b8060ff16601b14158015610e9557508060ff16601c14155b15610ea35760009350610f0a565b60408051600080825260208083018085528a905260ff8516838501526060830187905260808301869052925160019360a0808501949193601f19840193928390039091019190865af1158015610efd573d6000803e3d6000fd5b5050506020604051035193505b50505092915050565b6000828201838110156103a057600080fd5b6000803d8015610f3c5760208114610f4557610f51565b60019150610f51565b60206000803e60005191505b5015159190505600a165627a7a723058203583cf1ee43578aa8c3415971f450968da74ea150b7843ba541dabea9a63aa840029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _toAddress (address): 0x0000000000000000000000000000000000000000
Arg [1] : _tokenAddress (address): 0x0000000000000000000000000000000000000000
Arg [2] : _tokenAmount (uint256): 0
Arg [3] : _periodSeconds (uint256): 0
Arg [4] : _gasPrice (uint256): 0
-----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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.