Skip to content

Commit

Permalink
chore: retrieve old GaugeProxy
Browse files Browse the repository at this point in the history
  • Loading branch information
wei3erHase committed May 18, 2022
1 parent d0600e5 commit 2e86860
Show file tree
Hide file tree
Showing 3 changed files with 1,116 additions and 0 deletions.
1 change: 1 addition & 0 deletions .solhintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ node_modules
contracts/mock
contracts/for-test

contracts/GaugeProxy.sol
contracts/claim.sol
contracts/distribution.sol
contracts/faucet.sol
Expand Down
355 changes: 355 additions & 0 deletions contracts/GaugeProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
/**
*Submitted for verification at Etherscan.io on 2021-08-07
*/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

library Math {
function max(uint a, uint b) internal pure returns (uint) {
return a >= b ? a : b;
}
function min(uint a, uint b) internal pure returns (uint) {
return a < b ? a : b;
}
}

interface erc20 {
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint amount) external returns (bool);
function decimals() external view returns (uint8);
function balanceOf(address) external view returns (uint);
function transferFrom(address sender, address recipient, uint amount) external returns (bool);
function approve(address spender, uint value) external returns (bool);
}

interface ve {
function locked__end(address) external view returns (uint);
function deposit_for(address, uint) external;
}

interface delegate {
function get_adjusted_ve_balance(address, address) external view returns (uint);
}

contract Gauge {
address constant _ibff = 0xb347132eFf18a3f63426f4988ef626d2CbE274F5;
address constant _veibff = 0x4D0518C9136025903751209dDDdf6C67067357b1;
address constant _delegate = 0x0ea89fb2E5b8FA8F14b741ffe1A4617A32611DfC;
address constant _vedist = 0x15E61581AFa2707bca42Bae529387eEa11f68E6e;

uint constant DURATION = 7 days;
uint constant PRECISION = 10 ** 18;
uint constant MAXTIME = 4 * 365 * 86400;

address public immutable stake;
address immutable distribution;

uint public rewardRate;
uint public periodFinish;
uint public lastUpdateTime;
uint public rewardPerTokenStored;

modifier onlyDistribution() {
require(msg.sender == distribution);
_;
}

mapping(address => uint) public userRewardPerTokenPaid;
mapping(address => uint) public rewards;

uint public totalSupply;
uint public derivedSupply;
mapping(address => uint) public balanceOf;
mapping(address => uint) public derivedBalances;

constructor(address _stake) {
stake = _stake;
distribution = msg.sender;
}

function lastTimeRewardApplicable() public view returns (uint) {
return Math.min(block.timestamp, periodFinish);
}

function rewardPerToken() public view returns (uint) {
if (totalSupply == 0) {
return rewardPerTokenStored;
}
return rewardPerTokenStored + ((lastTimeRewardApplicable() - lastUpdateTime) * rewardRate * PRECISION / derivedSupply);
}

function derivedBalance(address account) public view returns (uint) {
uint _balance = balanceOf[account];
uint _derived = _balance * 40 / 100;
uint _adjusted = (totalSupply * delegate(_delegate).get_adjusted_ve_balance(account, address(this)) / erc20(_veibff).totalSupply()) * 60 / 100;
return Math.min(_derived + _adjusted, _balance);
}

function kick(address account) public {
uint _derivedBalance = derivedBalances[account];
derivedSupply -= _derivedBalance;
_derivedBalance = derivedBalance(account);
derivedBalances[account] = _derivedBalance;
derivedSupply += _derivedBalance;
}

function earned(address account) public view returns (uint) {
return (derivedBalances[account] * (rewardPerToken() - userRewardPerTokenPaid[account]) / PRECISION) + rewards[account];
}

function getRewardForDuration() external view returns (uint) {
return rewardRate * DURATION;
}

function deposit() external {
_deposit(erc20(stake).balanceOf(msg.sender), msg.sender);
}

function deposit(uint amount) external {
_deposit(amount, msg.sender);
}

function deposit(uint amount, address account) external {
_deposit(amount, account);
}

function _deposit(uint amount, address account) internal updateReward(account) {
totalSupply += amount;
balanceOf[account] += amount;
_safeTransferFrom(stake, account, address(this), amount);
}

function withdraw() external {
_withdraw(balanceOf[msg.sender]);
}

function withdraw(uint amount) external {
_withdraw(amount);
}

function _withdraw(uint amount) internal updateReward(msg.sender) {
totalSupply -= amount;
balanceOf[msg.sender] -= amount;
_safeTransfer(stake, msg.sender, amount);
}

function getReward() public updateReward(msg.sender) {
uint _reward = rewards[msg.sender];
uint _user_lock = ve(_veibff).locked__end(msg.sender);
uint _adj = Math.min(_reward * (_user_lock - block.timestamp) / MAXTIME, _reward);
if (_adj > 0) {
rewards[msg.sender] = 0;
_safeTransfer(_ibff, msg.sender, _adj);
ve(_veibff).deposit_for(msg.sender, _adj);
_safeTransfer(_ibff, _vedist, _reward - _adj);
}
}

function exit() external {
_withdraw(balanceOf[msg.sender]);
getReward();
}

function notifyRewardAmount(uint amount) external onlyDistribution updateReward(address(0)) {
if (block.timestamp >= periodFinish) {
rewardRate = amount / DURATION;
} else {
uint _remaining = periodFinish - block.timestamp;
uint _left = _remaining * rewardRate;
rewardRate = (amount + _left) / DURATION;
}

lastUpdateTime = block.timestamp;
periodFinish = block.timestamp + DURATION;
}

modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
if (account != address(0)) {
kick(account);
}
}

function _safeTransfer(address token, address to, uint256 value) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(erc20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))));
}

function _safeTransferFrom(address token, address from, address to, uint256 value) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(erc20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
}

contract GaugeProxy {
address constant _ibff = 0xb347132eFf18a3f63426f4988ef626d2CbE274F5;
address constant _delegate = 0x0ea89fb2E5b8FA8F14b741ffe1A4617A32611DfC;
address constant ZERO_ADDRESS = 0x0000000000000000000000000000000000000000;

uint public totalWeight;

address public gov;
address public nextgov;
uint public commitgov;
uint public constant delay = 1 days;

address[] internal _tokens;
mapping(address => address) public gauges; // token => gauge
mapping(address => uint) public weights; // token => weight
mapping(address => mapping(address => uint)) public votes; // msg.sender => votes
mapping(address => address[]) public tokenVote;// msg.sender => token
mapping(address => uint) public usedWeights; // msg.sender => total voting weight of user
mapping(address => bool) public enabled;

function tokens() external view returns (address[] memory) {
return _tokens;
}

constructor() {
gov = msg.sender;
}

modifier g() {
require(msg.sender == gov);
_;
}

function setGov(address _gov) external g {
nextgov = _gov;
commitgov = block.timestamp + delay;
}

function acceptGov() external {
require(msg.sender == nextgov && commitgov < block.timestamp);
gov = nextgov;
}

function reset() external {
_reset(msg.sender);
}

function _reset(address _owner) internal {
address[] storage _tokenVote = tokenVote[_owner];
uint _tokenVoteCnt = _tokenVote.length;

for (uint i = 0; i < _tokenVoteCnt; i ++) {
address _token = _tokenVote[i];
uint _votes = votes[_owner][_token];

if (_votes > 0) {
totalWeight -= _votes;
weights[_token] -= _votes;
votes[_owner][_token] = 0;
}
}

delete tokenVote[_owner];
}

function poke(address _owner) public {
address[] memory _tokenVote = tokenVote[_owner];
uint _tokenCnt = _tokenVote.length;
uint[] memory _weights = new uint[](_tokenCnt);

uint _prevUsedWeight = usedWeights[_owner];
uint _weight = delegate(_delegate).get_adjusted_ve_balance(_owner, ZERO_ADDRESS);

for (uint i = 0; i < _tokenCnt; i ++) {
uint _prevWeight = votes[_owner][_tokenVote[i]];
_weights[i] = _prevWeight * _weight / _prevUsedWeight;
}

_vote(_owner, _tokenVote, _weights);
}

function _vote(address _owner, address[] memory _tokenVote, uint[] memory _weights) internal {
// _weights[i] = percentage * 100
_reset(_owner);
uint _tokenCnt = _tokenVote.length;
uint _weight = delegate(_delegate).get_adjusted_ve_balance(_owner, ZERO_ADDRESS);
uint _totalVoteWeight = 0;
uint _usedWeight = 0;

for (uint i = 0; i < _tokenCnt; i ++) {
_totalVoteWeight += _weights[i];
}

for (uint i = 0; i < _tokenCnt; i ++) {
address _token = _tokenVote[i];
address _gauge = gauges[_token];
uint _tokenWeight = _weights[i] * _weight / _totalVoteWeight;

if (_gauge != address(0x0)) {
_usedWeight += _tokenWeight;
totalWeight += _tokenWeight;
weights[_token] += _tokenWeight;
tokenVote[_owner].push(_token);
votes[_owner][_token] = _tokenWeight;
}
}

usedWeights[_owner] = _usedWeight;
}

function vote(address[] calldata _tokenVote, uint[] calldata _weights) external {
require(_tokenVote.length == _weights.length);
_vote(msg.sender, _tokenVote, _weights);
}

function addGauge(address _token) external g {
require(gauges[_token] == address(0x0), "exists");
address _gauge = address(new Gauge(_token));
gauges[_token] = _gauge;
enabled[_token] = true;
_tokens.push(_token);
}

function disable(address _token) external g {
enabled[_token] = false;
}

function enable(address _token) external g {
enabled[_token] = true;
}

function length() external view returns (uint) {
return _tokens.length;
}

function distribute() external {
uint _balance = erc20(_ibff).balanceOf(address(this));
if (_balance > 0 && totalWeight > 0) {
uint _totalWeight = totalWeight;
for (uint i = 0; i < _tokens.length; i++) {
if (!enabled[_tokens[i]]) {
_totalWeight -= weights[_tokens[i]];
}
}
for (uint x = 0; x < _tokens.length; x++) {
if (enabled[_tokens[x]]) {
uint _reward = _balance * weights[_tokens[x]] / _totalWeight;
if (_reward > 0) {
address _gauge = gauges[_tokens[x]];
_safeTransfer(_ibff, _gauge, _reward);
Gauge(_gauge).notifyRewardAmount(_reward);
}
}
}
}
}

function _safeTransfer(address token, address to, uint256 value) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(erc20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
}
Loading

0 comments on commit 2e86860

Please sign in to comment.