ETH Price: $2,416.31 (+3.35%)

Contract

0xa560D06AAB7eE2FF17F3a5517a982a3eD9C5Da9A
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
172485652023-05-13 4:01:47490 days ago1683950507  Contract Creation0 ETH
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x644DB28D...87DFD510A
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
TokenPool

Compiler Version
v0.6.7+commit.b8d736ae

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 2 : GebRewards.sol
/// GebLenderFirstResortRewards.sol

// Copyright (C) 2021 Reflexer Labs, INC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

pragma solidity 0.6.7;

import "./utils/ReentrancyGuard.sol";

abstract contract TokenLike {
    function decimals() virtual public view returns (uint8);
    function totalSupply() virtual public view returns (uint256);
    function balanceOf(address) virtual public view returns (uint256);
    function mint(address, uint) virtual public;
    function burn(address, uint) virtual public;
    function approve(address, uint256) virtual external returns (bool);
    function transfer(address, uint256) virtual external returns (bool);
    function transferFrom(address,address,uint256) virtual external returns (bool);
}
abstract contract RewardDripperLike {
    function dripReward() virtual external;
    function dripReward(address) virtual external;
    function rewardPerBlock() virtual external view returns (uint256);
    function rewardToken() virtual external view returns (TokenLike);
}

// Stores tokens, owned by GebLenderFirstResortRewards
contract TokenPool {
    TokenLike public token;
    address   public owner;

    constructor(address token_) public {
        token = TokenLike(token_);
        owner = msg.sender;
    }

    // @notice Transfers tokens from the pool (callable by owner only)
    function transfer(address to, uint256 wad) public {
        require(msg.sender == owner, "unauthorized");
        require(token.transfer(to, wad), "TokenPool/failed-transfer");
    }

    // @notice Returns token balance of the pool
    function balance() public view returns (uint256) {
        return token.balanceOf(address(this));
    }
}

contract GebRewards is ReentrancyGuard {
    // --- Auth ---
    mapping (address => uint) public authorizedAccounts;
    /**
     * @notice Add auth to an account
     * @param account Account to add auth to
     */
    function addAuthorization(address account) virtual external isAuthorized {
        authorizedAccounts[account] = 1;
        emit AddAuthorization(account);
    }
    /**
     * @notice Remove auth from an account
     * @param account Account to remove auth from
     */
    function removeAuthorization(address account) virtual external isAuthorized {
        authorizedAccounts[account] = 0;
        emit RemoveAuthorization(account);
    }
    /**
    * @notice Checks whether msg.sender can call an authed function
    **/
    modifier isAuthorized {
        require(authorizedAccounts[msg.sender] == 1, "GebLenderFirstResortRewards/account-not-authorized");
        _;
    }

    // --- Variables ---
    // Flag that allows/blocks joining
    bool      public canJoin;
    // Last block when a reward was pulled
    uint256   public lastRewardBlock;
    // Amount of rewards per share accumulated (total, see rewardDebt for more info)
    uint256   public accTokensPerShare;
    // Balance of the rewards token in this contract since last update
    uint256   public rewardsBalance;
    // Staked Supply (== sum of all staked balances)
    uint256   public stakedSupply;

    // Balances (not affected by slashing)
    mapping(address => uint256)     public descendantBalanceOf;
    // The amount of tokens inneligible for claiming rewards (see formula below)
    mapping(address => uint256)     internal rewardDebt;
    // Pending reward = (descendant.balanceOf(user) * accTokensPerShare) - rewardDebt[user]

    // The token being deposited in the pool
    TokenPool            public ancestorPool;
    // The token used to pay rewards
    TokenPool            public rewardPool;
    // Contract that drips rewards
    RewardDripperLike    public rewardDripper;

    // --- Events ---
    event AddAuthorization(address account);
    event RemoveAuthorization(address account);
    event ModifyParameters(bytes32 indexed parameter, uint256 data);
    event ModifyParameters(bytes32 indexed parameter, address data);
    event ToggleJoin(bool canJoin);
    event Join(address indexed account, uint256 amount);
    event Exit(address indexed account, uint256 amount);
    event RewardsPaid(address account, uint256 amount);
    event PoolUpdated(uint256 accTokensPerShare, uint256 stakedSupply);

    constructor(
      address ancestor_,
      address rewardToken_,
      address rewardDripper_
    ) public {
        require(rewardDripper_ != address(0), "GebLenderFirstResortRewards/null-reward-dripper");
        require(ancestor_ != address(0), "GebLenderFirstResortRewards/null-descendant");

        authorizedAccounts[msg.sender] = 1;
        canJoin                        = true;

        rewardDripper                  = RewardDripperLike(rewardDripper_);

        ancestorPool                   = new TokenPool(ancestor_);
        rewardPool                     = new TokenPool(rewardToken_);

        lastRewardBlock                = block.number;

        require(ancestorPool.token().decimals() == 18, "GebLenderFirstResortRewards/ancestor-decimal-mismatch");

        emit AddAuthorization(msg.sender);
    }

    // --- Boolean Logic ---
    function both(bool x, bool y) internal pure returns (bool z) {
        assembly{ z := and(x, y)}
    }
    function either(bool x, bool y) internal pure returns (bool z) {
        assembly{ z := or(x, y)}
    }

    // --- Math ---
    uint256 public constant WAD = 10 ** 18;
    uint256 public constant RAY = 10 ** 27;

    function addition(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x + y) >= x, "GebLenderFirstResortRewards/add-overflow");
    }
    function subtract(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x - y) <= x, "GebLenderFirstResortRewards/sub-underflow");
    }
    function multiply(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x, "GebLenderFirstResortRewards/mul-overflow");
    }
    function wdivide(uint x, uint y) internal pure returns (uint z) {
        require(y > 0, "GebLenderFirstResortRewards/wdiv-by-zero");
        z = multiply(x, WAD) / y;
    }
    function wmultiply(uint x, uint y) internal pure returns (uint z) {
        z = multiply(x, y) / WAD;
    }

    // --- Administration ---
    /*
    * @notify Switch between allowing and disallowing joins
    */
    function toggleJoin() external isAuthorized {
        canJoin = !canJoin;
        emit ToggleJoin(canJoin);
    }
    /*
    * @notify Modify an address parameter
    * @param parameter The name of the parameter to modify
    * @param data New value for the parameter
    */
    function modifyParameters(bytes32 parameter, address data) external isAuthorized {
        require(data != address(0), "GebLenderFirstResortRewards/null-data");

        if (parameter == "rewardDripper") {
          rewardDripper = RewardDripperLike(data);
        }
        else revert("GebLenderFirstResortRewards/modify-unrecognized-param");
        emit ModifyParameters(parameter, data);
    }

    // --- Getters ---
    /*
    * @notify Return the ancestor token balance for this contract
    */
    function depositedAncestor() public view returns (uint256) {
        return ancestorPool.balance();
    }
    /*
    * @notice Returns unclaimed rewards for a given user
    * @param user The user for which to return pending rewards
    */
    function pendingRewards(address user) public view returns (uint256) {
        uint accTokensPerShare_ = accTokensPerShare;
        if (block.number > lastRewardBlock && stakedSupply != 0) {
            uint increaseInBalance = (block.number - lastRewardBlock) * rewardDripper.rewardPerBlock();
            accTokensPerShare_ = addition(accTokensPerShare_, multiply(increaseInBalance, RAY) / stakedSupply);
        }
        return subtract(multiply(descendantBalanceOf[user], accTokensPerShare_) / RAY, rewardDebt[user]);
    }

    /*
    * @notice Returns rewards earned per block for each token deposited (WAD)
    */
    function rewardRate() public view returns (uint256) {
        return (rewardDripper.rewardPerBlock() * WAD) / stakedSupply;
    }

    // --- Core Logic ---
    /*
    * @notify Updates the pool and pays rewards (if any)
    * @dev Must be included in deposits and withdrawals
    */
    modifier payRewards() {
        updatePool();

        if (descendantBalanceOf[msg.sender] > 0 && rewardPool.balance() > 0) {
            // Pays the reward
            uint256 pending = subtract(multiply(descendantBalanceOf[msg.sender], accTokensPerShare) / RAY, rewardDebt[msg.sender]);

            rewardPool.transfer(msg.sender, pending);
            rewardsBalance = rewardPool.balance();
            emit RewardsPaid(msg.sender, pending);
        }
        _;

        rewardDebt[msg.sender] = multiply(descendantBalanceOf[msg.sender], accTokensPerShare) / RAY;
    }

    /*
    * @notify Pays outstanding rewards to msg.sender
    */
    function getRewards() external nonReentrant payRewards {}

    /*
    * @notify Pull funds from the dripper
    */
    function pullFunds() public {
        rewardDripper.dripReward(address(rewardPool));
    }

    /*
    * @notify Updates pool data
    */
    function updatePool() public {
        if (block.number <= lastRewardBlock) return;
        lastRewardBlock = block.number;
        if (stakedSupply == 0) return;

        pullFunds();
        uint256 increaseInBalance = subtract(rewardPool.balance(), rewardsBalance);
        rewardsBalance = addition(rewardsBalance, increaseInBalance);

        // Updates distribution info
        accTokensPerShare = addition(accTokensPerShare, multiply(increaseInBalance, RAY) / stakedSupply);
        emit PoolUpdated(accTokensPerShare, stakedSupply);
    }

    /*
    * @notify Join ancestor tokens
    * @param wad The amount of ancestor tokens to join
    */
    function join(uint256 wad) external nonReentrant payRewards {
        require(canJoin, "GebLenderFirstResortRewards/join-not-allowed");
        require(wad > 0, "GebLenderFirstResortRewards/null-ancestor-to-join");

        require(ancestorPool.token().transferFrom(msg.sender, address(ancestorPool), wad), "GebLenderFirstResortRewards/could-not-transfer-ancestor");

        descendantBalanceOf[msg.sender] = addition(descendantBalanceOf[msg.sender], wad);
        stakedSupply = addition(stakedSupply, wad);

        emit Join(msg.sender, wad);
    }
    /*
    * @notice Exit a specific amount of ancestor tokens
    * @param wad The amount of tokens to exit
    */
    function exit(uint wad) external nonReentrant payRewards {
        require(wad > 0, "GebLenderFirstResortRewards/null-amount-to-exit");

        descendantBalanceOf[msg.sender] = subtract(descendantBalanceOf[msg.sender], wad);
        stakedSupply  = subtract(stakedSupply, wad);
        ancestorPool.transfer(msg.sender, wad);
        emit Exit(msg.sender, wad);
    }
}

File 2 of 2 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor () internal {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

Settings
{
  "remappings": [
    "ds-auth/=lib/ds-proxy/lib/ds-auth/src/",
    "ds-exec/=lib/ds-pause/lib/ds-spell/lib/ds-exec/src/",
    "ds-guard/=lib/geb-deploy/lib/ds-guard/src/",
    "ds-math/=lib/esm/lib/ds-token/lib/ds-math/src/",
    "ds-note/=lib/ds-proxy/lib/ds-note/src/",
    "ds-pause/=lib/ds-pause/src/",
    "ds-proxy/=lib/ds-proxy/src/",
    "ds-roles/=lib/ds-pause/lib/ds-vote-quorum/lib/ds-roles/src/",
    "ds-spell/=lib/ds-pause/lib/ds-spell/src/",
    "ds-stop/=lib/geb-fsm/lib/ds-stop/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "ds-thing/=lib/ds-value/lib/ds-thing/src/",
    "ds-token/=lib/esm/lib/ds-token/src/",
    "ds-value/=lib/ds-value/src/",
    "ds-vote-quorum/=lib/ds-pause/lib/ds-vote-quorum/src/",
    "ds-weth/=lib/ds-weth/",
    "erc20/=lib/ds-weth/lib/erc20/src/",
    "esm/=lib/esm/src/",
    "forge-std/=lib/forge-std/src/",
    "geb-basic-multisig/=lib/ds-pause/lib/geb-basic-multisig/src/",
    "geb-chainlink-median/=lib/geb-chainlink-median/src/",
    "geb-debt-popper-rewards/=lib/geb-debt-popper-rewards/src/",
    "geb-deploy/=lib/geb-deploy/src/",
    "geb-esm-threshold-setter/=lib/geb-esm-threshold-setter/src/",
    "geb-fsm/=lib/geb-fsm/src/",
    "geb-incentives/=lib/geb-proxy-actions/lib/geb-incentives/src/",
    "geb-lender-first-resort/=lib/geb-lender-first-resort/src/",
    "geb-pit/=lib/geb-pit/src/",
    "geb-protocol-token-authority/=lib/geb-protocol-token-authority/src/",
    "geb-proxy-actions/=lib/geb-proxy-actions/src/",
    "geb-proxy-registry/=lib/geb-proxy-registry/src/",
    "geb-rrfm-calculators/=lib/geb-rrfm-calculators/src/",
    "geb-rrfm-rate-setter/=lib/geb-rrfm-rate-setter/src/",
    "geb-safe-manager/=lib/geb-safe-manager/src/",
    "geb-safe-saviours/=lib/geb-proxy-actions/lib/geb-safe-saviours/src/",
    "geb-treasury-reimbursement/=lib/geb-debt-popper-rewards/lib/geb-treasury-reimbursement/src/",
    "geb-uniswap-median/=lib/geb-uniswap-median/src/",
    "geb/=lib/geb/src/",
    "mgl-debt-minter-rewards/=lib/mgl-debt-minter-rewards/",
    "mgl-emitter/=lib/mgl-emitter/src/",
    "multicall/=lib/multicall/src/"
  ],
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "istanbul",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract TokenLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80638da5cb5b14610051578063a9059cbb1461009b578063b69ef8a8146100e9578063fc0c546a14610107575b600080fd5b610059610151565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e7600480360360408110156100b157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610177565b005b6100f1610393565b6040518082815260200191505060405180910390f35b61010f610473565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461023a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f756e617574686f72697a6564000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156102e257600080fd5b505af11580156102f6573d6000803e3d6000fd5b505050506040513d602081101561030c57600080fd5b810190808051906020019092919050505061038f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e506f6f6c2f6661696c65642d7472616e736665720000000000000081525060200191505060405180910390fd5b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561043357600080fd5b505afa158015610447573d6000803e3d6000fd5b505050506040513d602081101561045d57600080fd5b8101908080519060200190929190505050905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea2646970667358221220841bedc81a3c1fce363f3e606642d5fd6e7d9ee5a82a3e0c329cd07ae000a6f164736f6c63430006070033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.