Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xf829d7014Db17D6DCe448bE958c7e4983cdb1F77
Balance 0 ETH
Nonce 1
Code Size 8298 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

8298 bytes
0x608060405234801561001057600080fd5b50600436106101375760003560e01c8063485cc955116100b85780639358928b1161007c5780639358928b1461039057806395d89b41146103ae578063a457c2d7146103cc578063a9059cbb146103fc578063dd62ed3e1461042c578063ee99205c1461045c57610137565b8063485cc955146102c057806361d027b3146102dc57806370a08231146102fa57806373c69eb71461032a5780637965d56d1461036057610137565b806323b872dd116100ff57806323b872dd146102085780632986c0e514610238578063313ce56714610256578063395093511461027457806340a5737f146102a457610137565b8063058ecdb41461013c57806306fdde031461016c578063095ea7b31461018a57806318160ddd146101ba5780631bd39674146101d8575b600080fd5b610156600480360381019061015191906117be565b61047a565b604051610163919061180d565b60405180910390f35b6101746106ae565b60405161018191906118b8565b60405180910390f35b6101a4600480360381019061019f9190611938565b610740565b6040516101b19190611993565b60405180910390f35b6101c2610757565b6040516101cf919061180d565b60405180910390f35b6101f260048036038101906101ed91906119ae565b610761565b6040516101ff919061180d565b60405180910390f35b610222600480360381019061021d91906119db565b610778565b60405161022f9190611993565b60405180910390f35b610240610afd565b60405161024d919061180d565b60405180910390f35b61025e610b0f565b60405161026b9190611a4a565b60405180910390f35b61028e60048036038101906102899190611938565b610b18565b60405161029b9190611993565b60405180910390f35b6102be60048036038101906102b991906119ae565b610bb6565b005b6102da60048036038101906102d59190611a65565b610c9d565b005b6102e4611079565b6040516102f19190611ab4565b60405180910390f35b610314600480360381019061030f9190611acf565b61109f565b604051610321919061180d565b60405180910390f35b610344600480360381019061033f91906119ae565b6110f5565b6040516103579796959493929190611afc565b60405180910390f35b61037a600480360381019061037591906119ae565b611147565b604051610387919061180d565b60405180910390f35b61039861115e565b6040516103a5919061180d565b60405180910390f35b6103b661119d565b6040516103c391906118b8565b60405180910390f35b6103e660048036038101906103e19190611938565b61122f565b6040516103f39190611993565b60405180910390f35b61041660048036038101906104119190611938565b6112eb565b6040516104239190611993565b60405180910390f35b61044660048036038101906104419190611a65565b61148a565b604051610453919061180d565b60405180910390f35b610464611511565b6040516104719190611ab4565b60405180910390f35b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461050c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050390611bdd565b60405180910390fd5b60008061051761115e565b9050600085036105a957837f0417b340e646d4be71f9b2da63b5c3c69bc9cfa069f0e0db4756271886130bf4600754604051610553919061180d565b60405180910390a2837f6012dbce857565c4a40974aa5de8373a761fc429077ef0c8c8611d1e20d63fb26000610587610afd565b604051610595929190611c42565b60405180910390a2600754925050506106a8565b60008111156105d25780600754866105c19190611c9a565b6105cb9190611d0b565b91506105d6565b8491505b816007546105e49190611d3c565b6007819055506000196fffffffffffffffffffffffffffffffff166007541115610624576000196fffffffffffffffffffffffffffffffff166007819055505b6007546611c37937e080007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61065a9190611d70565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6106859190611da1565b61068f9190611d0b565b600a819055506106a0818686611537565b600754925050505b92915050565b6060600380546106bd90611e04565b80601f01602080910402602001604051908101604052809291908181526020018280546106e990611e04565b80156107365780601f1061070b57610100808354040283529160200191610736565b820191906000526020600020905b81548152906001019060200180831161071957829003601f168201915b5050505050905090565b600061074d338484611698565b6001905092915050565b6000600254905090565b6000600a54826107719190611c9a565b9050919050565b600081600c60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546108029190611da1565b600c60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460405161095b919061180d565b60405180910390a3600061096e83610761565b905080600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546109bb9190611da1565b600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610a499190611d3c565b600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051610ae9919061180d565b60405180910390a360019150509392505050565b6000610b0a600654611147565b905090565b60006009905090565b6000610bac338484600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610ba79190611d3c565b611698565b6001905092915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c46576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3d90611ea7565b60405180910390fd5b600060065414610c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8290611f13565b60405180910390fd5b610c9481610761565b60068190555050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490611ea7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9390611f7f565b60405180910390fd5b81600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506611c37937e080007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610e109190611d70565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610e3b9190611da1565b600b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0690611feb565b60405180910390fd5b80600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600754604051610fd2919061180d565b60405180910390a37f817c653428858ed536dc085c5d8273734c517b55de44b55f5c5877a75e3373a1600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405161102b9190611ab4565b60405180910390a16000600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a54600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546110ee9190611d0b565b9050919050565b6009818154811061110557600080fd5b90600052602060002090600702016000915090508060000154908060010154908060020154908060030154908060040154908060050154908060060154905087565b6000600a54826111579190611d0b565b9050919050565b600061118b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661109f565b6007546111989190611da1565b905090565b6060600480546111ac90611e04565b80601f01602080910402602001604051908101604052809291908181526020018280546111d890611e04565b80156112255780601f106111fa57610100808354040283529160200191611225565b820191906000526020600020905b81548152906001019060200180831161120857829003601f168201915b5050505050905090565b600080600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508083106112c9576112c433856000611698565b6112e0565b6112df338585846112da9190611da1565b611698565b5b600191505092915050565b600080600a54836112fc9190611c9a565b905080600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113499190611da1565b600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113d79190611d3c565b600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef85604051611477919061180d565b60405180910390a3600191505092915050565b6000600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000808411156115635783670de0b6b3a7640000846115569190611c9a565b6115609190611d0b565b90505b60096040518060e0016040528084815260200183815260200186815260200161158a61115e565b815260200185815260200161159d610afd565b8152602001438152509080600181540180825580915050600190039060005260206000209060070201600090919091909150600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c082015181600601555050817f0417b340e646d4be71f9b2da63b5c3c69bc9cfa069f0e0db4756271886130bf4600754604051611649919061180d565b60405180910390a2817f6012dbce857565c4a40974aa5de8373a761fc429077ef0c8c8611d1e20d63fb28261167c610afd565b60405161168a92919061200b565b60405180910390a250505050565b80600c60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051611776919061180d565b60405180910390a3505050565b600080fd5b6000819050919050565b61179b81611788565b81146117a657600080fd5b50565b6000813590506117b881611792565b92915050565b600080604083850312156117d5576117d4611783565b5b60006117e3858286016117a9565b92505060206117f4858286016117a9565b9150509250929050565b61180781611788565b82525050565b600060208201905061182260008301846117fe565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611862578082015181840152602081019050611847565b60008484015250505050565b6000601f19601f8301169050919050565b600061188a82611828565b6118948185611833565b93506118a4818560208601611844565b6118ad8161186e565b840191505092915050565b600060208201905081810360008301526118d2818461187f565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611905826118da565b9050919050565b611915816118fa565b811461192057600080fd5b50565b6000813590506119328161190c565b92915050565b6000806040838503121561194f5761194e611783565b5b600061195d85828601611923565b925050602061196e858286016117a9565b9150509250929050565b60008115159050919050565b61198d81611978565b82525050565b60006020820190506119a86000830184611984565b92915050565b6000602082840312156119c4576119c3611783565b5b60006119d2848285016117a9565b91505092915050565b6000806000606084860312156119f4576119f3611783565b5b6000611a0286828701611923565b9350506020611a1386828701611923565b9250506040611a24868287016117a9565b9150509250925092565b600060ff82169050919050565b611a4481611a2e565b82525050565b6000602082019050611a5f6000830184611a3b565b92915050565b60008060408385031215611a7c57611a7b611783565b5b6000611a8a85828601611923565b9250506020611a9b85828601611923565b9150509250929050565b611aae816118fa565b82525050565b6000602082019050611ac96000830184611aa5565b92915050565b600060208284031215611ae557611ae4611783565b5b6000611af384828501611923565b91505092915050565b600060e082019050611b11600083018a6117fe565b611b1e60208301896117fe565b611b2b60408301886117fe565b611b3860608301876117fe565b611b4560808301866117fe565b611b5260a08301856117fe565b611b5f60c08301846117fe565b98975050505050505050565b7f5374616b696e67436f6e74726163743a202063616c6c206973206e6f7420737460008201527f616b696e6720636f6e7472616374000000000000000000000000000000000000602082015250565b6000611bc7602e83611833565b9150611bd282611b6b565b604082019050919050565b60006020820190508181036000830152611bf681611bba565b9050919050565b6000819050919050565b6000819050919050565b6000611c2c611c27611c2284611bfd565b611c07565b611788565b9050919050565b611c3c81611c11565b82525050565b6000604082019050611c576000830185611c33565b611c6460208301846117fe565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611ca582611788565b9150611cb083611788565b9250828202611cbe81611788565b91508282048414831517611cd557611cd4611c6b565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611d1682611788565b9150611d2183611788565b925082611d3157611d30611cdc565b5b828204905092915050565b6000611d4782611788565b9150611d5283611788565b9250828201905080821115611d6a57611d69611c6b565b5b92915050565b6000611d7b82611788565b9150611d8683611788565b925082611d9657611d95611cdc565b5b828206905092915050565b6000611dac82611788565b9150611db783611788565b9250828203905081811115611dcf57611dce611c6b565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611e1c57607f821691505b602082108103611e2f57611e2e611dd5565b5b50919050565b7f496e697469616c697a65723a202063616c6c6572206973206e6f7420696e697460008201527f69616c697a657200000000000000000000000000000000000000000000000000602082015250565b6000611e91602783611833565b9150611e9c82611e35565b604082019050919050565b60006020820190508181036000830152611ec081611e84565b9050919050565b7f43616e6e6f742073657420494e44455820616761696e00000000000000000000600082015250565b6000611efd601683611833565b9150611f0882611ec7565b602082019050919050565b60006020820190508181036000830152611f2c81611ef0565b9050919050565b7f5a65726f20616464726573733a205374616b696e670000000000000000000000600082015250565b6000611f69601583611833565b9150611f7482611f33565b602082019050919050565b60006020820190508181036000830152611f9881611f5c565b9050919050565b7f5a65726f20616464726573733a20547265617375727900000000000000000000600082015250565b6000611fd5601683611833565b9150611fe082611f9f565b602082019050919050565b6000602082019050818103600083015261200481611fc8565b9050919050565b600060408201905061202060008301856117fe565b61202d60208301846117fe565b939250505056fea26469706673582212201e11c74329ef0d8d7b3b172a2668f0189a4948bfc0cc70b1496ac83a2494fe0e64736f6c63430008130033

Verified Source Code Full Match

Compiler: v0.8.19+commit.7dd6d404 EVM: paris Optimization: No
sHATE.sol 247 lines
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.19;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../interface/IsHATE.sol";
import "../interface/IStaking.sol";

contract sHATE is IsHATE, ERC20 {
    /* ========== EVENTS ========== */

    event LogSupply(uint256 indexed epoch, uint256 totalSupply);
    event LogRebase(uint256 indexed epoch, uint256 rebase, uint256 index);
    event LogStakingContractUpdated(address stakingContract);

    /* ========== MODIFIERS ========== */

    modifier onlyStakingContract() {
        require(msg.sender == stakingContract, "StakingContract:  call is not staking contract");
        _;
    }

    /* ========== DATA STRUCTURES ========== */

    struct Rebase {
        uint256 epoch;
        uint256 rebase; // 18 decimals
        uint256 totalStakedBefore;
        uint256 totalStakedAfter;
        uint256 amountRebased;
        uint256 index;
        uint256 blockNumberOccured;
    }

    /* ========== STATE VARIABLES ========== */

    address internal initializer;

    uint256 internal INDEX; // Index Gons - tracks rebase growth

    uint256 internal _totalSupply;

    address public stakingContract; // balance used to calc rebase

    Rebase[] public rebases; // past rebase data

    uint256 private constant MAX_UINT256 = type(uint256).max;
    uint256 private constant INITIAL_FRAGMENTS_SUPPLY = 5_000_000 * 10**9;

    // TOTAL_GONS is a multiple of INITIAL_FRAGMENTS_SUPPLY so that _gonsPerFragment is an integer.
    // Use the highest value that fits in a uint256 for max granularity.
    uint256 private constant TOTAL_GONS = MAX_UINT256 - (MAX_UINT256 % INITIAL_FRAGMENTS_SUPPLY);

    // MAX_SUPPLY = maximum integer < (sqrt(4*TOTAL_GONS + 1) - 1) / 2
    uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1

    uint256 private _gonsPerFragment;
    mapping(address => uint256) private _gonBalances;

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

    address public treasury;

    /* ========== CONSTRUCTOR ========== */

    constructor() ERC20("Staked HATE", "sHATE") {
        initializer = msg.sender;
        _totalSupply = INITIAL_FRAGMENTS_SUPPLY;
        _gonsPerFragment = TOTAL_GONS / _totalSupply;
    }

    function decimals() public view virtual override returns (uint8) {
        return 9;
    }

    /* ========== INITIALIZATION ========== */

    function setIndex(uint256 _index) external {
        require(msg.sender == initializer, "Initializer:  caller is not initializer");
        require(INDEX == 0, "Cannot set INDEX again");
        INDEX = gonsForBalance(_index);
    }

    function initialize(address _stakingContract, address _treasury) external {
        require(msg.sender == initializer, "Initializer:  caller is not initializer");

        require(_stakingContract != address(0), "Zero address: Staking");
        stakingContract = _stakingContract;
        _gonBalances[stakingContract] = TOTAL_GONS;

        require(_treasury != address(0), "Zero address: Treasury");
        treasury = _treasury;

        emit Transfer(address(0x0), stakingContract, _totalSupply);
        emit LogStakingContractUpdated(stakingContract);

        initializer = address(0);
    }

    /* ========== REBASE ========== */

    /**
        @notice increases sHATE supply
        @param amount_ uint256
        @return uint256
     */
    function rebase(uint256 amount_, uint256 epoch_) public override onlyStakingContract returns (uint256) {
        uint256 rebaseAmount;
        uint256 circulatingSupply_ = circulatingSupply();
        if (amount_ == 0) {
            emit LogSupply(epoch_, _totalSupply);
            emit LogRebase(epoch_, 0, index());
            return _totalSupply;
        } else if (circulatingSupply_ > 0) {
            rebaseAmount = amount_ * _totalSupply / circulatingSupply_;
        } else {
            rebaseAmount = amount_;
        }

        _totalSupply = _totalSupply + rebaseAmount;

        if (_totalSupply > MAX_SUPPLY) {
            _totalSupply = MAX_SUPPLY;
        }

        _gonsPerFragment = TOTAL_GONS / _totalSupply;

        _storeRebase(circulatingSupply_, amount_, epoch_);

        return _totalSupply;
    }

    /**
        @notice emits event with data about rebase
        @param previousCirculating_ uint
        @param profit_ uint
        @param epoch_ uint
     */
    function _storeRebase(
        uint256 previousCirculating_,
        uint256 profit_,
        uint256 epoch_
    ) internal {
        uint256 rebasePercent;
        if (previousCirculating_ > 0) rebasePercent = profit_ * 1e18 / previousCirculating_;
        rebases.push(
            Rebase({
                epoch: epoch_,
                rebase: rebasePercent, // 18 decimals
                totalStakedBefore: previousCirculating_,
                totalStakedAfter: circulatingSupply(),
                amountRebased: profit_,
                index: index(),
                blockNumberOccured: block.number
            })
        );

        emit LogSupply(epoch_, _totalSupply);
        emit LogRebase(epoch_, rebasePercent, index());
    }

    /* ========== MUTATIVE FUNCTIONS =========== */

    function transfer(address to, uint256 value) public override(IERC20, ERC20) returns (bool) {
        uint256 gonValue = value * _gonsPerFragment;

        _gonBalances[msg.sender] = _gonBalances[msg.sender] - gonValue;
        _gonBalances[to] = _gonBalances[to] + gonValue;

        emit Transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) public override(IERC20, ERC20) returns (bool) {
        _allowedValue[from][msg.sender] = _allowedValue[from][msg.sender] - value;
        emit Approval(from, msg.sender, _allowedValue[from][msg.sender]);

        uint256 gonValue = gonsForBalance(value);
        _gonBalances[from] = _gonBalances[from] - gonValue;
        _gonBalances[to] = _gonBalances[to] + gonValue;

        emit Transfer(from, to, value);
        return true;
    }

    function approve(address spender, uint256 value) public override(IERC20, ERC20) returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public override returns (bool) {
        _approve(msg.sender, spender, _allowedValue[msg.sender][spender] + addedValue);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public override returns (bool) {
        uint256 oldValue = _allowedValue[msg.sender][spender];
        if (subtractedValue >= oldValue) {
            _approve(msg.sender, spender, 0);
        } else {
            _approve(msg.sender, spender, oldValue - subtractedValue);
        }
        return true;
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function _approve(
        address owner,
        address spender,
        uint256 value
    ) internal virtual override {
        _allowedValue[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /* ========== VIEW FUNCTIONS ========== */

    function balanceOf(address who) public view override(IERC20, ERC20) returns (uint256) {
        return _gonBalances[who] / _gonsPerFragment;
    }

    function gonsForBalance(uint256 amount) public view override returns (uint256) {
        return amount * _gonsPerFragment;
    }

    function balanceForGons(uint256 gons) public view override returns (uint256) {
        return gons / _gonsPerFragment;
    }

    // Staking contract holds excess sHATE
    function circulatingSupply() public view override returns (uint256) {
        return
            _totalSupply - balanceOf(stakingContract);
    }

    function index() public view override returns (uint256) {
        return balanceForGons(INDEX);
    }

    function allowance(address owner_, address spender) public view override(IERC20, ERC20) returns (uint256) {
        return _allowedValue[owner_][spender];
    }
}
IsHATE.sol 16 lines
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.19;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IsHATE is IERC20 {
    function rebase(uint256 amount_, uint epoch_) external returns (uint256);

    function circulatingSupply() external view returns (uint256);

    function gonsForBalance(uint amount) external view returns (uint);

    function balanceForGons(uint gons) external view returns (uint);

    function index() external view returns (uint);
}
IStaking.sol 18 lines
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.19;

interface IStaking {
    function stake(
        address _to,
        uint256 _amount
    ) external;

    function unstake(
        address _to,
        uint256 _amount
    ) external;

    function rebase() external;

    function index() external view returns (uint256);
}
Context.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
ERC20.sol 389 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: 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
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}
IERC20Metadata.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceForGons 0x7965d56d → uint256
balanceOf 0x70a08231 → uint256
circulatingSupply 0x9358928b → uint256
decimals 0x313ce567 → uint8
gonsForBalance 0x1bd39674 → uint256
index 0x2986c0e5 → uint256
name 0x06fdde03 → string
rebases 0x73c69eb7 → uint256, uint256, uint256, uint256, uint256, uint256, uint256
stakingContract 0xee99205c → address
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
treasury 0x61d027b3 → address

Write Contract 8 functions

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

approve 0x095ea7b3
address spender
uint256 value
returns: bool
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
initialize 0x485cc955
address _stakingContract
address _treasury
rebase 0x058ecdb4
uint256 amount_
uint256 epoch_
returns: uint256
setIndex 0x40a5737f
uint256 _index
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool

Recent Transactions

No transactions found for this address