ETH Price: $3,759.17 (-3.28%)

Transaction Decoder

Block:
7877508 at Jun-02-2019 02:41:10 AM +UTC
Transaction Fee:
0.000094052 ETH $0.35
Gas Used:
47,026 Gas / 2 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
(MiningPoolHub: Old Address)
5,492.778331920295347029 Eth5,492.778425972295347029 Eth0.000094052
0xe4eAb999...dfbaA230f
0.25000573002773889 Eth
Nonce: 74
0.24991167802773889 Eth
Nonce: 75
0.000094052
0xfD017478...a30e7C7A9
(MCH: Daily Action 2)

Execution Trace

MCHDailyActionV2.requestDailyActionReward( _signature=0xFEC7651FE0F35BBB792E9E6DBB08B757B55141EAB8CE47B6D394FE261FB43C551D036F4AB560FBB8C16EA9CB1CB0F861DFB23FA69DEEB6CF96207B7C3B69579D01, _referrer=0x0000000000000000000000000000000000000000 )
  • Null: 0x000...001.a6bdf22a( )
    pragma solidity 0.5.2;
    
    // File: contracts/lib/github.com/OpenZeppelin/openzeppelin-solidity-2.1.1/contracts/cryptography/ECDSA.sol
    
    /**
     * @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 memory 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.
            // solhint-disable-next-line no-inline-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
    
            // 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 {
                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));
        }
    }
    
    // File: contracts/lib/github.com/OpenZeppelin/openzeppelin-solidity-2.1.1/contracts/ownership/Ownable.sol
    
    /**
     * @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 private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev The Ownable constructor sets the original `owner` of the contract to the sender
         * account.
         */
        constructor () internal {
            _owner = msg.sender;
            emit OwnershipTransferred(address(0), _owner);
        }
    
        /**
         * @return the address of the owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner());
            _;
        }
    
        /**
         * @return true if `msg.sender` is the owner of the contract.
         */
        function isOwner() public view returns (bool) {
            return 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 OwnershipTransferred(_owner, address(0));
            _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;
        }
    }
    
    // File: contracts/lib/github.com/OpenZeppelin/openzeppelin-solidity-2.1.1/contracts/access/Roles.sol
    
    /**
     * @title Roles
     * @dev Library for managing addresses assigned to a Role.
     */
    library Roles {
        struct Role {
            mapping (address => bool) bearer;
        }
    
        /**
         * @dev give an account access to this role
         */
        function add(Role storage role, address account) internal {
            require(account != address(0));
            require(!has(role, account));
    
            role.bearer[account] = true;
        }
    
        /**
         * @dev remove an account's access to this role
         */
        function remove(Role storage role, address account) internal {
            require(account != address(0));
            require(has(role, account));
    
            role.bearer[account] = false;
        }
    
        /**
         * @dev check if an account has this role
         * @return bool
         */
        function has(Role storage role, address account) internal view returns (bool) {
            require(account != address(0));
            return role.bearer[account];
        }
    }
    
    // File: contracts/lib/github.com/OpenZeppelin/openzeppelin-solidity-2.1.1/contracts/access/roles/PauserRole.sol
    
    contract PauserRole {
        using Roles for Roles.Role;
    
        event PauserAdded(address indexed account);
        event PauserRemoved(address indexed account);
    
        Roles.Role private _pausers;
    
        constructor () internal {
            _addPauser(msg.sender);
        }
    
        modifier onlyPauser() {
            require(isPauser(msg.sender));
            _;
        }
    
        function isPauser(address account) public view returns (bool) {
            return _pausers.has(account);
        }
    
        function addPauser(address account) public onlyPauser {
            _addPauser(account);
        }
    
        function renouncePauser() public {
            _removePauser(msg.sender);
        }
    
        function _addPauser(address account) internal {
            _pausers.add(account);
            emit PauserAdded(account);
        }
    
        function _removePauser(address account) internal {
            _pausers.remove(account);
            emit PauserRemoved(account);
        }
    }
    
    // File: contracts/lib/github.com/OpenZeppelin/openzeppelin-solidity-2.1.1/contracts/lifecycle/Pausable.sol
    
    /**
     * @title Pausable
     * @dev Base contract which allows children to implement an emergency stop mechanism.
     */
    contract Pausable is PauserRole {
        event Paused(address account);
        event Unpaused(address account);
    
        bool private _paused;
    
        constructor () internal {
            _paused = false;
        }
    
        /**
         * @return true if the contract is paused, false otherwise.
         */
        function paused() public view returns (bool) {
            return _paused;
        }
    
        /**
         * @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 onlyPauser whenNotPaused {
            _paused = true;
            emit Paused(msg.sender);
        }
    
        /**
         * @dev called by the owner to unpause, returns to normal state
         */
        function unpause() public onlyPauser whenPaused {
            _paused = false;
            emit Unpaused(msg.sender);
        }
    }
    
    // File: contracts/lib/github.com/OpenZeppelin/openzeppelin-solidity-2.1.1/contracts/math/SafeMath.sol
    
    /**
     * @title SafeMath
     * @dev Unsigned math operations with safety checks that revert on error
     */
    library SafeMath {
        /**
        * @dev Multiplies two unsigned integers, 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 unsigned integers truncating the quotient, reverts on division by zero.
        */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 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 unsigned integers, 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 unsigned integers, 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 unsigned integers 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;
        }
    }
    
    // File: contracts/MCHDailyActionV2.sol
    
    contract MCHDailyActionV2 is Ownable, Pausable {
        using SafeMath for uint256;
    
        uint256 public term;
        address public validater;
        mapping(address => mapping(address => uint256)) public counter;
        mapping(address => uint256) public latestActionTime;
    
        event Action(
            address indexed user,
            address indexed referrer,
            uint256 at
        );
        
        constructor() public {
            term = 86400 - 600;
        }
        
        function withdrawEther() external onlyOwner() {
            msg.sender.transfer(address(this).balance);
        }
    
        function setValidater(address _varidater) external onlyOwner() {
            validater = _varidater;
        }
    
        function updateTerm(uint256 _term) external onlyOwner() {
            term = _term;
        }
    
        function requestDailyActionReward(bytes calldata _signature, address _referrer) external whenNotPaused() {
            require(!isInTerm(msg.sender), "this sender got daily reward within term");
            uint256 count = getCount(msg.sender);
            require(validateSig(_signature, count), "invalid signature");
            emit Action(
                msg.sender,
                _referrer,
                block.timestamp
            );
            setCount(msg.sender, count + 1);
            latestActionTime[msg.sender] = block.timestamp;
        }
    
        function isInTerm(address _sender) public view returns (bool) {
            if (latestActionTime[_sender] == 0) {
                return false;
            } else if (block.timestamp >= latestActionTime[_sender].add(term)) {
                return false;
            }
            return true;
        }
    
        function getCount(address _sender) public view returns (uint256) {
            if (counter[validater][_sender] == 0) {
                return 1;
            }
            return counter[validater][_sender];
        }
    
        function setCount(address _sender, uint256 _count) private {
            counter[validater][_sender] = _count;
        }
    
        function validateSig(bytes memory _signature, uint256 _count) private view returns (bool) {
            require(validater != address(0));
            uint256 hash = uint256(msg.sender) * _count;
            address signer = ECDSA.recover(ECDSA.toEthSignedMessageHash(bytes32(hash)), _signature);
            return (signer == validater);
        }
    
        /* function getAddress(bytes32 hash, bytes memory signature) public pure returns (address) { */
        /*     return ECDSA.recover(ECDSA.toEthSignedMessageHash(hash), signature); */
        /* } */
    
    }