ETH Price: $2,395.87 (-4.51%)

Transaction Decoder

Block:
7718366 at May-08-2019 06:17:44 AM +UTC
Transaction Fee:
0.000085817 ETH $0.21
Gas Used:
85,817 Gas / 1 Gwei

Emitted Events:

104 WednesdayCoin.Transfer( _from=[Receiver] Airdrop, _to=[Sender] 0x2a7ab8b76983f4a99a01a2c900c2cb39f25f2b6d, _value=2000000000000000000000 )
105 Airdrop.Claim( airdropId=4A2C9A445C9E17DFFD08B22004F3BC8A9A298CE8057E89C763A01142DF719F74, user=[Sender] 0x2a7ab8b76983f4a99a01a2c900c2cb39f25f2b6d )

Account State Difference:

  Address   Before After State Difference Code
(DwarfPool)
713.223104690540914728 Eth713.223190507540914728 Eth0.000085817
0x2a7Ab8b7...9F25f2B6d
0.000525570777956096 Eth
Nonce: 5
0.000439753777956096 Eth
Nonce: 6
0.000085817
0x35223BC9...475853551
0x7848ae8F...308BDfAbD

Execution Trace

Airdrop.claim( airdropId=4A2C9A445C9E17DFFD08B22004F3BC8A9A298CE8057E89C763A01142DF719F74 )
  • Airdrop.isCollected( user=0x2a7Ab8b76983f4A99a01a2c900C2Cb39F25f2B6d, airdropId=4A2C9A445C9E17DFFD08B22004F3BC8A9A298CE8057E89C763A01142DF719F74 ) => ( False )
  • WednesdayCoin.transfer( _to=0x2a7Ab8b76983f4A99a01a2c900C2Cb39F25f2B6d, _value=2000000000000000000000 ) => ( success=True )
    File 1 of 2: Airdrop
    pragma solidity ^0.4.24;
    
    /**
     * @title -Airdrop
     * every erc20 token can doAirdrop here 
     * Contact us for further cooperation [email protected]
     *
     *  █████╗  ██╗ ██████╗  ██████╗  ██████╗   ██████╗  ██████╗
     * ██╔══██╗ ██║ ██╔══██╗ ██╔══██╗ ██╔══██╗ ██╔═══██╗ ██╔══██╗
     * ███████║ ██║ ██████╔╝ ██║  ██║ ██████╔╝ ██║   ██║ ██████╔╝
     * ██╔══██║ ██║ ██╔══██╗ ██║  ██║ ██╔══██╗ ██║   ██║ ██╔═══╝
     * ██║  ██║ ██║ ██║  ██║ ██████╔╝ ██║  ██║ ╚██████╔╝ ██║
     * ╚═╝  ╚═╝ ╚═╝ ╚═╝  ╚═╝ ╚═════╝  ╚═╝  ╚═╝  ╚═════╝  ╚═╝
     *
     * ---
     * POWERED BY
     * ╦   ╔═╗ ╦═╗ ╔╦╗ ╦   ╔═╗ ╔═╗ ╔═╗      ╔╦╗ ╔═╗ ╔═╗ ╔╦╗
     * ║   ║ ║ ╠╦╝  ║║ ║   ║╣  ╚═╗ ╚═╗       ║  ║╣  ╠═╣ ║║║
     * ╩═╝ ╚═╝ ╩╚═ ═╩╝ ╩═╝ ╚═╝ ╚═╝ ╚═╝       ╩  ╚═╝ ╩ ╩ ╩ ╩
     * game at http://lordless.games
     * code at https://github.com/lordlessio
     */
    
    
    /**
     * @title Ownable
     * @dev The Ownable contract has an owner address, and provides basic authorization control
     * functions, this simplifies the implementation of "user permissions".
     */
    contract Ownable {
      address public owner;
    
    
      event OwnershipRenounced(address indexed previousOwner);
      event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
      );
    
    
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      constructor() public {
        owner = msg.sender;
      }
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(msg.sender == owner);
        _;
      }
    
      /**
       * @dev Allows the current owner to relinquish control of the contract.
       * @notice Renouncing to ownership will leave the contract without an owner.
       * It will not be possible to call the functions with the `onlyOwner`
       * modifier anymore.
       */
      function renounceOwnership() public onlyOwner {
        emit OwnershipRenounced(owner);
        owner = address(0);
      }
    
      /**
       * @dev Allows the current owner to transfer control of the contract to a newOwner.
       * @param _newOwner The address to transfer ownership to.
       */
      function transferOwnership(address _newOwner) public onlyOwner {
        _transferOwnership(_newOwner);
      }
    
      /**
       * @dev Transfers control of the contract to a newOwner.
       * @param _newOwner The address to transfer ownership to.
       */
      function _transferOwnership(address _newOwner) internal {
        require(_newOwner != address(0));
        emit OwnershipTransferred(owner, _newOwner);
        owner = _newOwner;
      }
    }
    
    
    /**
     * @title Pausable
     * @dev Base contract which allows children to implement an emergency stop mechanism.
     */
    contract Pausable is Ownable {
      event Pause();
      event Unpause();
    
      bool public paused = false;
    
    
      /**
       * @dev Modifier to make a function callable only when the contract is not paused.
       */
      modifier whenNotPaused() {
        require(!paused);
        _;
      }
    
      /**
       * @dev Modifier to make a function callable only when the contract is paused.
       */
      modifier whenPaused() {
        require(paused);
        _;
      }
    
      /**
       * @dev called by the owner to pause, triggers stopped state
       */
      function pause() public onlyOwner whenNotPaused {
        paused = true;
        emit Pause();
      }
    
      /**
       * @dev called by the owner to unpause, returns to normal state
       */
      function unpause() public onlyOwner whenPaused {
        paused = false;
        emit Unpause();
      }
    }
    
    
    /**
     * @title Roles
     * @author Francisco Giordano (@frangio)
     * @dev Library for managing addresses assigned to a Role.
     * See RBAC.sol for example usage.
     */
    library Roles {
      struct Role {
        mapping (address => bool) bearer;
      }
    
      /**
       * @dev give an address access to this role
       */
      function add(Role storage _role, address _addr)
        internal
      {
        _role.bearer[_addr] = true;
      }
    
      /**
       * @dev remove an address' access to this role
       */
      function remove(Role storage _role, address _addr)
        internal
      {
        _role.bearer[_addr] = false;
      }
    
      /**
       * @dev check if an address has this role
       * // reverts
       */
      function check(Role storage _role, address _addr)
        internal
        view
      {
        require(has(_role, _addr));
      }
    
      /**
       * @dev check if an address has this role
       * @return bool
       */
      function has(Role storage _role, address _addr)
        internal
        view
        returns (bool)
      {
        return _role.bearer[_addr];
      }
    }
    
    
    /**
     * @title RBAC (Role-Based Access Control)
     * @author Matt Condon (@Shrugs)
     * @dev Stores and provides setters and getters for roles and addresses.
     * Supports unlimited numbers of roles and addresses.
     * See //contracts/mocks/RBACMock.sol for an example of usage.
     * This RBAC method uses strings to key roles. It may be beneficial
     * for you to write your own implementation of this interface using Enums or similar.
     */
    contract RBAC {
      using Roles for Roles.Role;
    
      mapping (string => Roles.Role) private roles;
    
      event RoleAdded(address indexed operator, string role);
      event RoleRemoved(address indexed operator, string role);
    
      /**
       * @dev reverts if addr does not have role
       * @param _operator address
       * @param _role the name of the role
       * // reverts
       */
      function checkRole(address _operator, string _role)
        public
        view
      {
        roles[_role].check(_operator);
      }
    
      /**
       * @dev determine if addr has role
       * @param _operator address
       * @param _role the name of the role
       * @return bool
       */
      function hasRole(address _operator, string _role)
        public
        view
        returns (bool)
      {
        return roles[_role].has(_operator);
      }
    
      /**
       * @dev add a role to an address
       * @param _operator address
       * @param _role the name of the role
       */
      function addRole(address _operator, string _role)
        internal
      {
        roles[_role].add(_operator);
        emit RoleAdded(_operator, _role);
      }
    
      /**
       * @dev remove a role from an address
       * @param _operator address
       * @param _role the name of the role
       */
      function removeRole(address _operator, string _role)
        internal
      {
        roles[_role].remove(_operator);
        emit RoleRemoved(_operator, _role);
      }
    
      /**
       * @dev modifier to scope access to a single role (uses msg.sender as addr)
       * @param _role the name of the role
       * // reverts
       */
      modifier onlyRole(string _role)
      {
        checkRole(msg.sender, _role);
        _;
      }
    
      /**
       * @dev modifier to scope access to a set of roles (uses msg.sender as addr)
       * @param _roles the names of the roles to scope access to
       * // reverts
       *
       * @TODO - when solidity supports dynamic arrays as arguments to modifiers, provide this
       *  see: https://github.com/ethereum/solidity/issues/2467
       */
      // modifier onlyRoles(string[] _roles) {
      //     bool hasAnyRole = false;
      //     for (uint8 i = 0; i < _roles.length; i++) {
      //         if (hasRole(msg.sender, _roles[i])) {
      //             hasAnyRole = true;
      //             break;
      //         }
      //     }
    
      //     require(hasAnyRole);
    
      //     _;
      // }
    }
    
    
    /**
     * @title Superuser
     * @dev The Superuser contract defines a single superuser who can transfer the ownership
     * of a contract to a new address, even if he is not the owner.
     * A superuser can transfer his role to a new address.
     */
    contract Superuser is Ownable, RBAC {
      string public constant ROLE_SUPERUSER = "superuser";
    
      constructor () public {
        addRole(msg.sender, ROLE_SUPERUSER);
      }
    
      /**
       * @dev Throws if called by any account that's not a superuser.
       */
      modifier onlySuperuser() {
        checkRole(msg.sender, ROLE_SUPERUSER);
        _;
      }
    
      modifier onlyOwnerOrSuperuser() {
        require(msg.sender == owner || isSuperuser(msg.sender));
        _;
      }
    
      /**
       * @dev getter to determine if address has superuser role
       */
      function isSuperuser(address _addr)
        public
        view
        returns (bool)
      {
        return hasRole(_addr, ROLE_SUPERUSER);
      }
    
      /**
       * @dev Allows the current superuser to transfer his role to a newSuperuser.
       * @param _newSuperuser The address to transfer ownership to.
       */
      function transferSuperuser(address _newSuperuser) public onlySuperuser {
        require(_newSuperuser != address(0));
        removeRole(msg.sender, ROLE_SUPERUSER);
        addRole(_newSuperuser, ROLE_SUPERUSER);
      }
    
      /**
       * @dev Allows the current superuser or owner to transfer control of the contract to a newOwner.
       * @param _newOwner The address to transfer ownership to.
       */
      function transferOwnership(address _newOwner) public onlyOwnerOrSuperuser {
        _transferOwnership(_newOwner);
      }
    }
    
    
    /**
     * @title SafeMath
     */
    library SafeMath {
      /**
      * @dev Integer division of two numbers, truncating the quotient.
      */
      function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws 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 a / b;
      }
    
      /**
      * @dev Multiplies two numbers, throws on overflow.
      */
      function mul(uint256 a, uint256 b) 
          internal 
          pure 
          returns (uint256 c) 
      {
        if (a == 0) {
          return 0;
        }
        c = a * b;
        require(c / a == b, "SafeMath mul failed");
        return c;
      }
    
      /**
      * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
      */
      function sub(uint256 a, uint256 b)
          internal
          pure
          returns (uint256) 
      {
        require(b <= a, "SafeMath sub failed");
        return a - b;
      }
    
      /**
      * @dev Adds two numbers, throws on overflow.
      */
      function add(uint256 a, uint256 b)
          internal
          pure
          returns (uint256 c) 
      {
        c = a + b;
        require(c >= a, "SafeMath add failed");
        return c;
      }
      
      /**
        * @dev gives square root of given x.
        */
      function sqrt(uint256 x)
          internal
          pure
          returns (uint256 y) 
      {
        uint256 z = ((add(x,1)) / 2);
        y = x;
        while (z < y) 
        {
          y = z;
          z = ((add((x / z),z)) / 2);
        }
      }
      
      /**
        * @dev gives square. batchplies x by x
        */
      function sq(uint256 x)
          internal
          pure
          returns (uint256)
      {
        return (mul(x,x));
      }
      
      /**
        * @dev x to the power of y 
        */
      function pwr(uint256 x, uint256 y)
          internal 
          pure 
          returns (uint256)
      {
        if (x==0)
            return (0);
        else if (y==0)
            return (1);
        else 
        {
          uint256 z = x;
          for (uint256 i=1; i < y; i++)
            z = mul(z,x);
          return (z);
        }
      }
    }
    
    
    /**
     * @title -airdrop Interface
     */
    
    interface IAirdrop {
    
      function isVerifiedUser(address user) external view returns (bool);
      function isCollected(address user, bytes32 airdropId) external view returns (bool);
      function getAirdropIds()external view returns(bytes32[]);
      function getAirdropIdsByContractAddress(address contractAddress)external view returns(bytes32[]);
      function getUser(address userAddress) external view returns (
        address,
        string,
        uint256,
        uint256
      );
      function getAirdrop(
        bytes32 airdropId
        ) external view returns (address, uint256, bool);
      function updateVeifyFee(uint256 fee) external;
      function verifyUser(string name) external payable;
      function addAirdrop (address contractAddress, uint256 countPerUser, bool needVerifiedUser) external;
      function claim(bytes32 airdropId) external;
      function withdrawToken(address contractAddress, address to) external;
      function withdrawEth(address to) external;
    
      
      
    
      /* Events */
    
      event UpdateVeifyFee (
        uint256 indexed fee
      );
    
      event VerifyUser (
        address indexed user
      );
    
      event AddAirdrop (
        address indexed contractAddress,
        uint256 countPerUser,
        bool needVerifiedUser
      );
    
      event Claim (
        bytes32 airdropId,
        address user
      );
    
      event WithdrawToken (
        address indexed contractAddress,
        address to,
        uint256 count
      );
    
      event WithdrawEth (
        address to,
        uint256 count
      );
    }
    
    
    
    
    
    
    
    contract ERC20Interface {
      function transfer(address to, uint tokens) public returns (bool success);
      function transferFrom(address from, address to, uint tokens) public returns (bool success);
      function balanceOf(address tokenOwner) public view returns (uint balance);
    }
    contract Airdrop is Superuser, Pausable, IAirdrop {
    
      using SafeMath for *;
    
      struct User {
        address user;
        string name;
        uint256 verifytime;
        uint256 verifyFee;
      }
    
      struct Airdrop {
        address contractAddress;
        uint256 countPerUser; // wei
        bool needVerifiedUser;
      }
    
      uint256 public verifyFee = 2e16; // 0.02 eth
      bytes32[] public airdropIds; //
    
      mapping (address => User) public userAddressToUser;
      mapping (address => bytes32[]) contractAddressToAirdropId;
      mapping (bytes32 => Airdrop) airdropIdToAirdrop;
      mapping (bytes32 => mapping (address => bool)) airdropIdToUserAddress;
      mapping (address => uint256) contractAddressToAirdropCount;
    
    
      function isVerifiedUser(address user) external view returns (bool){
        return userAddressToUser[user].user == user;
      }
    
      function isCollected(address user, bytes32 airdropId) external view returns (bool) {
        return airdropIdToUserAddress[airdropId][user];
      }
    
      function getAirdropIdsByContractAddress(address contractAddress)external view returns(bytes32[]){
        return contractAddressToAirdropId[contractAddress];
      }
      function getAirdropIds()external view returns(bytes32[]){
        return airdropIds;
      }
    
      function tokenTotalClaim(address contractAddress)external view returns(uint256){
        return contractAddressToAirdropCount[contractAddress];
      }
    
      function getUser(
        address userAddress
        ) external view returns (address, string, uint256 ,uint256){
        User storage user = userAddressToUser[userAddress];
        return (user.user, user.name, user.verifytime, user.verifyFee);
      }
    
      function getAirdrop(
        bytes32 airdropId
        ) external view returns (address, uint256, bool){
        Airdrop storage airdrop = airdropIdToAirdrop[airdropId];
        return (airdrop.contractAddress, airdrop.countPerUser, airdrop.needVerifiedUser);
      }
      
      function updateVeifyFee(uint256 fee) external onlyOwnerOrSuperuser{
        verifyFee = fee;
        emit UpdateVeifyFee(fee);
      }
    
      function verifyUser(string name) external payable whenNotPaused {
        address sender = msg.sender;
        require(!this.isVerifiedUser(sender), "Is Verified User");
        uint256 _ethAmount = msg.value;
        require(_ethAmount >= verifyFee, "LESS FEE");
        uint256 payExcess = _ethAmount.sub(verifyFee);
        if(payExcess > 0) {
          sender.transfer(payExcess);
        }
        
        User memory _user = User(
          sender,
          name,
          block.timestamp,
          verifyFee
        );
    
        userAddressToUser[sender] = _user;
        emit VerifyUser(msg.sender);
      }
    
      function addAirdrop(address contractAddress, uint256 countPerUser, bool needVerifiedUser) external onlyOwnerOrSuperuser{
        bytes32 airdropId = keccak256(
          abi.encodePacked(block.timestamp, contractAddress, countPerUser, needVerifiedUser)
        );
    
        Airdrop memory _airdrop = Airdrop(
          contractAddress,
          countPerUser,
          needVerifiedUser
        );
        airdropIdToAirdrop[airdropId] = _airdrop;
        airdropIds.push(airdropId);
        contractAddressToAirdropId[contractAddress].push(airdropId);
        emit AddAirdrop(contractAddress, countPerUser, needVerifiedUser);
      }
    
      function claim(bytes32 airdropId) external whenNotPaused {
    
        Airdrop storage _airdrop = airdropIdToAirdrop[airdropId];
        if (_airdrop.needVerifiedUser) {
          require(this.isVerifiedUser(msg.sender));
        }
        
        require(!this.isCollected(msg.sender, airdropId), "The same Airdrop can only be collected once per address.");
        ERC20Interface erc20 = ERC20Interface(_airdrop.contractAddress);
        erc20.transfer(msg.sender, _airdrop.countPerUser);
        airdropIdToUserAddress[airdropId][msg.sender] = true;
        // update to
        contractAddressToAirdropCount[_airdrop.contractAddress] = 
          contractAddressToAirdropCount[_airdrop.contractAddress].add(_airdrop.countPerUser);
        emit Claim(airdropId, msg.sender);
      }
    
      function withdrawToken(address contractAddress, address to) external onlyOwnerOrSuperuser {
        ERC20Interface erc20 = ERC20Interface(contractAddress);
        uint256 balance = erc20.balanceOf(address(this));
        erc20.transfer(to, balance);
        emit WithdrawToken(contractAddress, to, balance);
      }
    
      function withdrawEth(address to) external onlySuperuser {
        uint256 balance = address(this).balance;
        to.transfer(balance);
        emit WithdrawEth(to, balance);
      }
    
    }

    File 2 of 2: WednesdayCoin
    pragma solidity ^0.4.4;
    
    contract Token {
    
        /// @return total amount of tokens
        function totalSupply() constant returns (uint256 supply) {}
    
        /// @param _owner The address from which the balance will be retrieved
        /// @return The balance
        function balanceOf(address _owner) constant returns (uint256 balance) {}
    
        /// @notice send `_value` token to `_to` from `msg.sender`
        /// @param _to The address of the recipient
        /// @param _value The amount of token to be transferred
        /// @return Whether the transfer was successful or not
        function transfer(address _to, uint256 _value) returns (bool success) {}
    
        /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
        /// @param _from The address of the sender
        /// @param _to The address of the recipient
        /// @param _value The amount of token to be transferred
        /// @return Whether the transfer was successful or not
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
    
        /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
        /// @param _spender The address of the account able to transfer the tokens
        /// @param _value The amount of wei to be approved for transfer
        /// @return Whether the approval was successful or not
        function approve(address _spender, uint256 _value) returns (bool success) {}
    
        /// @param _owner The address of the account owning tokens
        /// @param _spender The address of the account able to transfer the tokens
        /// @return Amount of remaining tokens allowed to spent
        function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
    
        event Transfer(address indexed _from, address indexed _to, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
    }
    
    contract StandardToken is Token {
    
        function transfer(address _to, uint256 _value) returns (bool success) {
            //Default assumes totalSupply can't be over max (2^256 - 1).
            //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
            //Replace the if with this one instead.
            //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
    
            //require Wednesday(3)
            uint8 dayOfWeek = uint8((now / 86400 + 4) % 7);
            require(dayOfWeek == 3);
    
            if (balances[msg.sender] >= _value && _value > 0) {
                balances[msg.sender] -= _value;
                balances[_to] += _value;
                Transfer(msg.sender, _to, _value);
                return true;
            } else {return false;}
        }
    
        function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
            //same as above. Replace this line with the following if you want to protect against wrapping uints.
            //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
    
            //require Wednesday(3)
            uint8 dayOfWeek = uint8((now / 86400 + 4) % 7);
            require(dayOfWeek == 3);
    
            if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
                balances[_to] += _value;
                balances[_from] -= _value;
                allowed[_from][msg.sender] -= _value;
                Transfer(_from, _to, _value);
                return true;
            } else {return false;}
        }
    
        function balanceOf(address _owner) constant returns (uint256 balance) {
            return balances[_owner];
        }
    
        function approve(address _spender, uint256 _value) returns (bool success) {
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
            return true;
        }
    
        function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
            return allowed[_owner][_spender];
        }
    
        mapping(address => uint256) balances;
        mapping(address => mapping(address => uint256)) allowed;
        uint256 public totalSupply;
    }
    
    
    //name this contract whatever you'd like
    contract WednesdayCoin is StandardToken {
    
        function() {
            //if ether is sent to this address, send it back.
            throw;
        }
    
        /* Public variables of the token */
    
        /*
        NOTE:
        The following variables are OPTIONAL vanities. One does not have to include them.
        They allow one to customise the token contract & in no way influences the core functionality.
        Some wallets/interfaces might not even bother to look at this information.
        */
        string public name;                   //fancy name: eg Simon Bucks
        uint8 public decimals;                //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.
        string public symbol;                 //An identifier: eg SBX
        string public version = 'WED2.0';       //WED 0.1 standard. Just an arbitrary versioning scheme.
    
        function WednesdayCoin() {
            balances[msg.sender] = 21000000000000000000000000000;
            // Give the creator all initial tokens (100000 for example)
            totalSupply = 21000000000000000000000000000;
            // Update total supply (100000 for example)
            name = "Wednesday Coin";
            // Set the name for display purposes
            decimals = 18;
            // Amount of decimals for display purposes
            symbol = "WED";
            // Set the symbol for display purposes
        }
    
        /* Approves and then calls the receiving contract */
        function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
            allowed[msg.sender][_spender] = _value;
            Approval(msg.sender, _spender, _value);
    
            //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
            //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
            //it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.
            if (!_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) {throw;}
            return true;
        }
    }