Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0x399c4a6f640f5cF5575C4d04Fec9d28DF383aC85
Balance 0 ETH
Nonce 1
Code Size 9190 bytes
Indexed Transactions 0 (1 on-chain, 1.0% indexed)
External Etherscan · Sourcify

Contract Bytecode

9190 bytes
0x608060405234801561001057600080fd5b50600436106101a35760003560e01c806374de4ec4116100ee578063a26dbf2611610097578063b9b5d1de11610071578063b9b5d1de14610442578063d66692a71461046f578063db2e21bc14610477578063f2fde38b1461047f576101a3565b8063a26dbf2614610415578063a694fc3a1461041d578063aa5c3ab41461043a576101a3565b80638f32d59b116100c85780638f32d59b146103e65780639946e341146103ee5780639d76ea581461040d576101a3565b806374de4ec4146103b9578063750142e6146103d65780638da5cb5b146103de576101a3565b80632c4e722e1161015057806350003ca61161012a57806350003ca6146103745780635b9f0016146103a7578063715018a6146103af576101a3565b80632c4e722e146103485780633ccfd60b146103505780633f683b6a1461036c576101a3565b80630f0a3d13116101815780630f0a3d13146102a75780631bbc4b83146102f25780632986c0e514610323576101a3565b806304554443146101a857806306fdde03146101c25780630ba36dcd1461023f575b600080fd5b6101b06104b2565b60408051918252519081900360200190f35b6101ca6104b8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102045781810151838201526020016101ec565b50505050905090810190601f1680156102315780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102726004803603602081101561025557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610564565b6040805196875260208701959095528585019390935260608501919091526080840152151560a0830152519081900360c00190f35b6102ce600480360360208110156102bd57600080fd5b503567ffffffffffffffff16610602565b6040805167ffffffffffffffff909316835260208301919091528051918290030190f35b6102fa610628565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61032b610649565b6040805167ffffffffffffffff9092168252519081900360200190f35b61032b610659565b610358610675565b604080519115158252519081900360200190f35b61035861080c565b6101b06004803603602081101561038a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610815565b6101b0610851565b6103b7610857565b005b610358600480360360208110156103cf57600080fd5b503561091f565b6101b0610b79565b6102fa610b7f565b610358610b9b565b6103b76004803603602081101561040457600080fd5b50351515610bd9565b6102fa610c9d565b6101b0610cb9565b6103586004803603602081101561043357600080fd5b5035610cbf565b6101b0610efa565b6103b76004803603604081101561045857600080fd5b5067ffffffffffffffff8135169060200135610f00565b6101b0611108565b61035861110e565b6103b76004803603602081101561049557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661129f565b600a5481565b600b805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561055c5780601f106105315761010080835404028352916020019161055c565b820191906000526020600020905b81548152906001019060200180831161053f57829003601f168201915b505050505081565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260408120548190819081908190819060ff16156105f95750505073ffffffffffffffffffffffffffffffffffffffff84166000908152600160208190526040909120805491810154600282015460038301546004840154600590940154949750919550935067ffffffffffffffff169160ff165b91939550919395565b6002602052600090815260409020805460019091015467ffffffffffffffff9091169082565b600d54610100900473ffffffffffffffffffffffffffffffffffffffff1681565b60095467ffffffffffffffff1681565b60095468010000000000000000900467ffffffffffffffff1681565b600033806106ca576040805162461bcd60e51b815260206004820152600c60248201527f5a65726f20616464726573730000000000000000000000000000000000000000604482015290519081900360640190fd5b3360009081526003602052604090205460ff1661072e576040805162461bcd60e51b815260206004820152601860248201527f4e6f207374616b657320666f756e6420666f7220757365720000000000000000604482015290519081900360640190fd5b33600090815260016020526040902060020154421015610795576040805162461bcd60e51b815260206004820152601b60248201527f52657175657374696e67206265666f7265206c6f636b2074696d650000000000604482015290519081900360640190fd5b3360009081526001602052604090206005015460ff16156107fd576040805162461bcd60e51b815260206004820152601060248201527f416c72656164792070616964206f757400000000000000000000000000000000604482015290519081900360640190fd5b61080633611304565b91505090565b600d5460ff1681565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040812060020154610849908390611528565b90505b919050565b60055481565b61085f610b9b565b6108b0576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60003380610974576040805162461bcd60e51b815260206004820152600c60248201527f5a65726f20616464726573730000000000000000000000000000000000000000604482015290519081900360640190fd5b60048054600d80547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff93841681029190911791829055604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523395810186905230602482015290518894600094939093049092169163dd62ed3e91604480820192602092909190829003018186803b158015610a2c57600080fd5b505afa158015610a40573d6000803e3d6000fd5b505050506040513d6020811015610a5657600080fd5b5051905080821115610a995760405162461bcd60e51b815260040180806020018281038252602181526020018061231d6021913960400191505060405180910390fd5b60008611610aee576040805162461bcd60e51b815260206004820152601760248201527f526577617264206d75737420626520706f736974697665000000000000000000604482015290519081900360640190fd5b600854610b01908763ffffffff61173e16565b600855600654610b17908763ffffffff61173e16565b600655610b24338761179f565b610b315760009450610b70565b6040805187815242602082015281517f40df43107e8b4d467127964bd3c966687c0a6a39aaede970755397fd09535e98929181900390910190a1600194505b50505050919050565b60085481565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b6000805473ffffffffffffffffffffffffffffffffffffffff16610bbd6117ac565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b610be1610b9b565b610c32576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600d80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215159081179091556040805191825242602083015280517f36e3f34a0ee7e675c6e4fb54887d109037e69fb0e40bffc3b86a4887960a019b9281900390910190a150565b60045473ffffffffffffffffffffffffffffffffffffffff1681565b600c5481565b60003380610d14576040805162461bcd60e51b815260206004820152600c60248201527f5a65726f20616464726573730000000000000000000000000000000000000000604482015290519081900360640190fd5b60048054600d80547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff93841681029190911791829055604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523395810186905230602482015290518894600094939093049092169163dd62ed3e91604480820192602092909190829003018186803b158015610dcc57600080fd5b505afa158015610de0573d6000803e3d6000fd5b505050506040513d6020811015610df657600080fd5b5051905080821115610e395760405162461bcd60e51b815260040180806020018281038252602181526020018061231d6021913960400191505060405180910390fd5b60008611610e8e576040805162461bcd60e51b815260206004820152601460248201527f43616e2774207374616b65203020616d6f756e74000000000000000000000000604482015290519081900360640190fd5b600d5460ff1615610ee6576040805162461bcd60e51b815260206004820152600e60248201527f5374616b696e6720706175736564000000000000000000000000000000000000604482015290519081900360640190fd5b610ef033876117b0565b9695505050505050565b60065481565b610f08610b9b565b610f59576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b67ffffffffffffffff8216610fb5576040805162461bcd60e51b815260206004820152601260248201527f5a65726f20696e74657265737420726174650000000000000000000000000000604482015290519081900360640190fd5b80611007576040805162461bcd60e51b815260206004820152601260248201527f5a65726f206c6f636b206475726174696f6e0000000000000000000000000000604482015290519081900360640190fd5b600980547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000007fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091166801000000000000000067ffffffffffffffff8681169182029290921783811660019184168201841617808655604080518082018252848152426020808301828152948816600090815260028252849020925183549099169888169890981782559251930192909255600a8790559454815193168352928201528082018490526060810192909252517fcef8b5fd0fe8d4a25244c395e72076a1d6a1b552c7116e90af6f8b2d7f61aeb0916080908290030190a15050565b60075481565b60003380611163576040805162461bcd60e51b815260206004820152600c60248201527f5a65726f20616464726573730000000000000000000000000000000000000000604482015290519081900360640190fd5b3360009081526003602052604090205460ff166111c7576040805162461bcd60e51b815260206004820152601860248201527f4e6f207374616b657320666f756e6420666f7220757365720000000000000000604482015290519081900360640190fd5b3360009081526001602052604090206002015442101561122e576040805162461bcd60e51b815260206004820152601b60248201527f52657175657374696e67206265666f7265206c6f636b2074696d650000000000604482015290519081900360640190fd5b3360009081526001602052604090206005015460ff1615611296576040805162461bcd60e51b815260206004820152601060248201527f416c72656164792070616964206f757400000000000000000000000000000000604482015290519081900360640190fd5b61080633611c2b565b6112a7610b9b565b6112f8576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b61130181611da5565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040812060020154819061133a908490611528565b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604090206004015490915061137790829063ffffffff61173e16565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260016020526040902054600654919250908211156113f8576040805162461bcd60e51b815260206004820152601260248201527f4e6f7420656e6f75676820726577617264730000000000000000000000000000604482015290519081900360640190fd5b60055461140b908263ffffffff611e8416565b600555600654611421908363ffffffff611e8416565b60065573ffffffffffffffffffffffffffffffffffffffff8416600090815260016020818152604080842060050180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116851790915560039092529092208054909216909155600c5461149c9163ffffffff611e8416565b600c556114b8846114b3838563ffffffff61173e16565b611ee1565b1561151e576004546040805183815260208101859052815173ffffffffffffffffffffffffffffffffffffffff8089169416927f85ab59351da11b79336de7647172267c33bf533ee87d9d292441c2672177159b928290030190a360019250505061084c565b5060009392505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081205460ff1661155d57506000611738565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160208190526040822080549181015460038201546002909201549293909267ffffffffffffffff90921691819081906115ba908663ffffffff611e8416565b9050835b60095467ffffffffffffffff90811690821610156116cd57600181810167ffffffffffffffff1660009081526002602052604090200154891015611601576116cd565b600181810167ffffffffffffffff166000908152600260205260409020015461162a9087611e84565b935061168c6116418361271063ffffffff611f4b16565b67ffffffffffffffff808416600090815260026020526040902054611680918891611674918d911663ffffffff611f4b16565b9063ffffffff611f4b16565b9063ffffffff611fa416565b925061169e878463ffffffff61173e16565b600191820167ffffffffffffffff811660009081526002602052604090208301549198509096509401936115be565b5087851015611730576116e6888663ffffffff611e8416565b925061172d6116fd8261271063ffffffff611f4b16565b67ffffffffffffffff8087166000908152600260205260409020546116809116611674878b63ffffffff611f4b16565b91505b509450505050505b92915050565b600082820183811015611798576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600061179883308461200e565b3390565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081205460ff1661195a5773ffffffffffffffffffffffffffffffffffffffff831660009081526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055815160c0810183528481524291810191909152600a54909182019061186d9061186090610e1063ffffffff611f4b16565b429063ffffffff61173e16565b815260095467ffffffffffffffff90811660208084019190915260006040808501829052606094850182905273ffffffffffffffffffffffffffffffffffffffff891682526001808452918190208651815592860151838301558501516002830155928401516003820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909316179091556080830151600482015560a090920151600590920180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692151592909217909155600c546119529161173e565b600c55611b49565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604090206002015442106119c05760405162461bcd60e51b815260040180806020018281038252602d815260200180612385602d913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260408120546119f6908463ffffffff61173e16565b73ffffffffffffffffffffffffffffffffffffffff851660009081526001602052604081206004015491925090611a3d90611a318742611528565b9063ffffffff61173e16565b90506040518060c00160405280838152602001428152602001611a70611860610e10600a54611f4b90919063ffffffff16565b815260095467ffffffffffffffff9081166020808401919091526040808401959095526000606093840181905273ffffffffffffffffffffffffffffffffffffffff8a168152600180835290869020855181559185015190820155938301516002850155908201516003840180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016919092161790556080810151600483015560a00151600590910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055505b600554611b5c908363ffffffff61173e16565b600555600754611b72908363ffffffff61173e16565b600755611b7f838361179f565b611bd0576040805162461bcd60e51b815260206004820152600e60248201527f5061796d656e74206661696c6564000000000000000000000000000000000000604482015290519081900360640190fd5b60045460408051848152905173ffffffffffffffffffffffffffffffffffffffff8087169316917f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd7919081900360200190a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040812054600554611c64908263ffffffff611e8416565b600590815573ffffffffffffffffffffffffffffffffffffffff8416600090815260016020818152604080842090940180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090811684179091556003909152929091208054909216909155600c54611ce29163ffffffff611e8416565b600c556000611cf18483611ee1565b905080611d45576040805162461bcd60e51b815260206004820152600c60248201527f4572726f7220706179696e670000000000000000000000000000000000000000604482015290519081900360640190fd5b6004546040805184815260006020820152815173ffffffffffffffffffffffffffffffffffffffff8089169416927f85ab59351da11b79336de7647172267c33bf533ee87d9d292441c2672177159b928290030190a35060019392505050565b73ffffffffffffffffffffffffffffffffffffffff8116611df75760405162461bcd60e51b815260040180806020018281038252602681526020018061233e6026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600082821115611edb576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600454600d80547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff93841681029190911791829055600092611f42929190910416848461219f565b50600192915050565b600082611f5a57506000611738565b82820282848281611f6757fe5b04146117985760405162461bcd60e51b81526004018080602001828103825260218152602001806123646021913960400191505060405180910390fd5b6000808211611ffa576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161200557fe5b04949350505050565b60048054600d80547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff93841681029190911791829055604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815288851695810195909552306024860152516000948894879487949004169163dd62ed3e91604480820192602092909190829003018186803b1580156120c857600080fd5b505afa1580156120dc573d6000803e3d6000fd5b505050506040513d60208110156120f257600080fd5b50519050808211156121355760405162461bcd60e51b815260040180806020018281038252602181526020018061231d6021913960400191505060405180910390fd5b600454600d80547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff9384168102919091179182905561219292910416888888612260565b5060019695505050505050565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561222657600080fd5b505af115801561223a573d6000803e3d6000fd5b505050506040513d602081101561225057600080fd5b505161225b57600080fd5b505050565b604080517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528481166024830152604482018490529151918616916323b872dd916064808201926020929091908290030181600087803b1580156122e157600080fd5b505af11580156122f5573d6000803e3d6000fd5b505050506040513d602081101561230b57600080fd5b505161231657600080fd5b5050505056fe4d616b65207375726520746f2061646420656e6f75676820616c6c6f77616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774c6f636b20657870697265642c20706c6561736520776974686472617720616e64207374616b6520616761696ea265627a7a723158204c4e08ed313ea3a7e03906dd91104211cd48f40994a857694e308176dae6f0d264736f6c63430005100032

Verified Source Code Full Match

Compiler: v0.5.16+commit.9c3226ce EVM: istanbul Optimization: Yes (20000 runs)
Locking.sol 555 lines
pragma solidity 0.5.16;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */

interface IERC20 {
    function totalSupply() external view returns (uint256);

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

    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

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

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

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

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

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

// File: openzeppelin-solidity/contracts/math/SafeMath.sol

pragma solidity 0.5.16;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

pragma solidity 0.5.16;

contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor() internal {}

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode
        return msg.data;
    }
}

// File: @openzeppelin/contracts/ownership/Ownable.sol

pragma solidity 0.5.16;

contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    constructor() internal {
        _owner = _msgSender();
        emit OwnershipTransferred(address(0), _owner);
    }

    function owner() public view returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    function isOwner() public view returns (bool) {
        return _msgSender() == _owner;
    }

    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal {
        require(
            newOwner != address(0),
            "Ownable: new owner is the zero address"
        );
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

library SafeERC20 {
    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        require(token.transfer(to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        require(token.transferFrom(from, to, value));
    }

    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        require(token.approve(spender, value));
    }
}

pragma solidity 0.5.16;

contract IDOLocking is Ownable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    /**
     *  @dev Structs to store user staking data.
     */
    struct Deposits {
        uint256 depositAmount;
        uint256 depositTime;
        uint256 endTime;
        uint64 userIndex;
        uint256 rewards;
        bool paid;
    }

    /**
     *  @dev Structs to store interest rate change.
     */
    struct Rates {
        uint64 newInterestRate;
        uint256 timeStamp;
    }

    mapping(address => Deposits) private deposits;
    mapping(uint64 => Rates) public rates;
    mapping(address => bool) private hasStaked;

    address public tokenAddress;
    uint256 public stakedBalance;
    uint256 public rewardBalance;
    uint256 public stakedTotal;
    uint256 public totalReward;
    uint64 public index;
    uint64 public rate;
    uint256 public lockDuration;
    string public name;
    uint256 public totalParticipants;
    bool public isStopped;

    IERC20 public ERC20Interface;

    /**
     *  @dev Emitted when user stakes 'stakedAmount' value of tokens
     */
    event Staked(
        address indexed token,
        address indexed staker_,
        uint256 stakedAmount_
    );

    /**
     *  @dev Emitted when user withdraws his stakings
     */
    event PaidOut(
        address indexed token,
        address indexed staker_,
        uint256 amount_,
        uint256 reward_
    );

    event RateAndLockduration(
        uint64 index,
        uint64 newRate,
        uint256 lockDuration,
        uint256 time
    );

    event RewardsAdded(uint256 rewards, uint256 time);

    event StakingStopped(bool status, uint256 time);

    /**
     *   @param
     *   name_ name of the contract
     *   tokenAddress_ contract address of the token
     *   rate_ rate multiplied by 100
     *   lockduration_ duration in days
     */
    constructor(
        string memory name_,
        address tokenAddress_,
        uint64 rate_,
        uint256 lockDuration_
    ) public Ownable() {
        name = name_;
        require(tokenAddress_ != address(0), "Zero token address");
        tokenAddress = tokenAddress_;
        lockDuration = lockDuration_;
        require(rate_ != 0, "Zero interest rate");
        rate = rate_;
        rates[index] = Rates(rate, block.timestamp);
    }

    /**
     *  Requirements:
     *  `rate_` New effective interest rate multiplied by 100
     *  @dev to set interest rates
     *  `lockduration_' lock days
     *  @dev to set lock duration days
     */
    function setRateAndLockduration(uint64 rate_, uint256 lockduration_)
        external
        onlyOwner
    {
        require(rate_ != 0, "Zero interest rate");
        require(lockduration_ != 0, "Zero lock duration");
        rate = rate_;
        index++;
        rates[index] = Rates(rate_, block.timestamp);
        lockDuration = lockduration_;
        emit RateAndLockduration(index, rate_, lockduration_, block.timestamp);
    }

    function changeStakingStatus(bool _status) external onlyOwner {
        isStopped = _status;
        emit StakingStopped(_status, block.timestamp);
    }

    /**
     *  Requirements:
     *  `rewardAmount` rewards to be added to the staking contract
     *  @dev to add rewards to the staking contract
     *  once the allowance is given to this contract for 'rewardAmount' by the user
     */
    function addReward(uint256 rewardAmount)
        external
        _realAddress(msg.sender)
        _hasAllowance(msg.sender, rewardAmount)
        returns (bool)
    {
        require(rewardAmount > 0, "Reward must be positive");
        totalReward = totalReward.add(rewardAmount);
        rewardBalance = rewardBalance.add(rewardAmount);
        if (!_payMe(msg.sender, rewardAmount)) {
            return false;
        }
        emit RewardsAdded(rewardAmount, block.timestamp);
        return true;
    }

    /**
     *  Requirements:
     *  `user` User wallet address
     *  @dev returns user staking data
     */
    function userDeposits(address user)
        external
        view
        returns (
            uint256,
            uint256,
            uint256,
            uint256,
            uint256,
            bool
        )
    {
        if (hasStaked[user]) {
            return (
                deposits[user].depositAmount,
                deposits[user].depositTime,
                deposits[user].endTime,
                deposits[user].userIndex,
                deposits[user].rewards,
                deposits[user].paid
            );
        }
    }

    /**
     *  Requirements:
     *  `amount` Amount to be staked
     /**
     *  @dev to stake 'amount' value of tokens 
     *  once the user has given allowance to the staking contract
     */

    function stake(uint256 amount)
        external
        _realAddress(msg.sender)
        _hasAllowance(msg.sender, amount)
        returns (bool)
    {
        require(amount > 0, "Can't stake 0 amount");
        require(!isStopped, "Staking paused");
        return (_stake(msg.sender, amount));
    }

    function _stake(address from, uint256 amount) private returns (bool) {
        if (!hasStaked[from]) {
            hasStaked[from] = true;

            deposits[from] = Deposits(
                amount,
                block.timestamp,
                block.timestamp.add((lockDuration.mul(3600))),
                index,
                0,
                false
            );
            totalParticipants = totalParticipants.add(1);
        } else {
            require(
                block.timestamp < deposits[from].endTime,
                "Lock expired, please withdraw and stake again"
            );
            uint256 newAmount = deposits[from].depositAmount.add(amount);
            uint256 rewards = _calculate(from, block.timestamp).add(
                deposits[from].rewards
            );
            deposits[from] = Deposits(
                newAmount,
                block.timestamp,
                block.timestamp.add((lockDuration.mul(3600))),
                index,
                rewards,
                false
            );
        }
        stakedBalance = stakedBalance.add(amount);
        stakedTotal = stakedTotal.add(amount);
        require(_payMe(from, amount), "Payment failed");
        emit Staked(tokenAddress, from, amount);

        return true;
    }

    /**
     * @dev to withdraw user stakings after the lock period ends.
     */
    function withdraw() external _realAddress(msg.sender) returns (bool) {
        require(hasStaked[msg.sender], "No stakes found for user");
        require(
            block.timestamp >= deposits[msg.sender].endTime,
            "Requesting before lock time"
        );
        require(!deposits[msg.sender].paid, "Already paid out");
        return (_withdraw(msg.sender));
    }

    function _withdraw(address from) private returns (bool) {
        uint256 reward = _calculate(from, deposits[from].endTime);
        reward = reward.add(deposits[from].rewards);
        uint256 amount = deposits[from].depositAmount;

        require(reward <= rewardBalance, "Not enough rewards");

        stakedBalance = stakedBalance.sub(amount);
        rewardBalance = rewardBalance.sub(reward);
        deposits[from].paid = true;
        hasStaked[from] = false;
        totalParticipants = totalParticipants.sub(1);

        if (_payDirect(from, amount.add(reward))) {
            emit PaidOut(tokenAddress, from, amount, reward);
            return true;
        }
        return false;
    }

    function emergencyWithdraw()
        external
        _realAddress(msg.sender)
        returns (bool)
    {
        require(hasStaked[msg.sender], "No stakes found for user");
        require(
            block.timestamp >= deposits[msg.sender].endTime,
            "Requesting before lock time"
        );
        require(!deposits[msg.sender].paid, "Already paid out");

        return (_emergencyWithdraw(msg.sender));
    }

    function _emergencyWithdraw(address from) private returns (bool) {
        uint256 amount = deposits[from].depositAmount;
        stakedBalance = stakedBalance.sub(amount);
        deposits[from].paid = true;
        hasStaked[from] = false; //Check-Effects-Interactions pattern
        totalParticipants = totalParticipants.sub(1);

        bool principalPaid = _payDirect(from, amount);
        require(principalPaid, "Error paying");
        emit PaidOut(tokenAddress, from, amount, 0);

        return true;
    }

    /**
     *  Requirements:
     *  `from` User wallet address
     * @dev to calculate the rewards based on user staked 'amount'
     * 'userIndex' - the index of the interest rate at the time of user stake.
     * 'depositTime' - time of staking
     */
    function calculate(address from) external view returns (uint256) {
        return _calculate(from, deposits[from].endTime);
    }

    function _calculate(address from, uint256 endTime)
        private
        view
        returns (uint256)
    {
        if (!hasStaked[from]) return 0;
        (uint256 amount, uint256 depositTime, uint64 userIndex) = (
            deposits[from].depositAmount,
            deposits[from].depositTime,
            deposits[from].userIndex
        );

        uint256 time;
        uint256 interest;
        uint256 _lockduration = deposits[from].endTime.sub(depositTime);
        for (uint64 i = userIndex; i < index; i++) {
            //loop runs till the latest index/interest rate change
            if (endTime < rates[i + 1].timeStamp) {
                //if the change occurs after the endTime loop breaks
                break;
            } else {
                time = rates[i + 1].timeStamp.sub(depositTime);
                interest = amount.mul(rates[i].newInterestRate).mul(time).div(
                    _lockduration.mul(10000)
                );
                amount = amount.add(interest);
                depositTime = rates[i + 1].timeStamp;
                userIndex++;
            }
        }

        if (depositTime < endTime) {
            //final calculation for the remaining time period
            time = endTime.sub(depositTime);

            interest = time
                .mul(amount)
                .mul(rates[userIndex].newInterestRate)
                .div(_lockduration.mul(10000));
        }

        return (interest);
    }

    function _payMe(address payer, uint256 amount) private returns (bool) {
        return _payTo(payer, address(this), amount);
    }

    function _payTo(
        address allower,
        address receiver,
        uint256 amount
    ) private _hasAllowance(allower, amount) returns (bool) {
        ERC20Interface = IERC20(tokenAddress);
        ERC20Interface.safeTransferFrom(allower, receiver, amount);
        return true;
    }

    function _payDirect(address to, uint256 amount) private returns (bool) {
        ERC20Interface = IERC20(tokenAddress);
        ERC20Interface.safeTransfer(to, amount);
        return true;
    }

    modifier _realAddress(address addr) {
        require(addr != address(0), "Zero address");
        _;
    }

    modifier _hasAllowance(address allower, uint256 amount) {
        // Make sure the allower has provided the right allowance.
        ERC20Interface = IERC20(tokenAddress);
        uint256 ourAllowance = ERC20Interface.allowance(allower, address(this));
        require(amount <= ourAllowance, "Make sure to add enough allowance");
        _;
    }
}

Read Contract

ERC20Interface 0x1bbc4b83 → address
calculate 0x50003ca6 → uint256
index 0x2986c0e5 → uint64
isOwner 0x8f32d59b → bool
isStopped 0x3f683b6a → bool
lockDuration 0x04554443 → uint256
name 0x06fdde03 → string
owner 0x8da5cb5b → address
rate 0x2c4e722e → uint64
rates 0x0f0a3d13 → uint64, uint256
rewardBalance 0xaa5c3ab4 → uint256
stakedBalance 0x5b9f0016 → uint256
stakedTotal 0xd66692a7 → uint256
tokenAddress 0x9d76ea58 → address
totalParticipants 0xa26dbf26 → uint256
totalReward 0x750142e6 → uint256
userDeposits 0x0ba36dcd → uint256, uint256, uint256, uint256, uint256, bool

Write Contract 8 functions

These functions modify contract state and require a wallet transaction to execute.

addReward 0x74de4ec4
uint256 rewardAmount
returns: bool
changeStakingStatus 0x9946e341
bool _status
emergencyWithdraw 0xdb2e21bc
No parameters
returns: bool
renounceOwnership 0x715018a6
No parameters
setRateAndLockduration 0xb9b5d1de
uint64 rate_
uint256 lockduration_
stake 0xa694fc3a
uint256 amount
returns: bool
transferOwnership 0xf2fde38b
address newOwner
withdraw 0x3ccfd60b
No parameters
returns: bool

Recent Transactions

This address has 1 on-chain transactions, but only 1.0% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →