编译器
0.8.14+commit.80d49f37
文件 1 的 3:DevFund.sol
pragma solidity 0.8.14;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract DevFund {
IERC20 public rewardToken;
IERC20 public holderToken;
uint256 public totalReward;
uint256 public prevBalance;
mapping(address => uint256) public rewardAtTimeOfWithdraw;
mapping(address => uint256) public owed;
constructor(address _rewardToken) {
rewardToken = IERC20(_rewardToken);
}
function setup(address _holderToken) external returns (bool){
require(address(holderToken) == address(0), "DevFund: already setup");
holderToken = IERC20(_holderToken);
return true;
}
function withdrawReward() public returns (uint256) {
updateTotalReward();
uint256 value = calcReward(msg.sender) + owed[msg.sender];
rewardAtTimeOfWithdraw[msg.sender] = totalReward;
owed[msg.sender] = 0;
require(value > 0, "DevFund: withdrawReward nothing to transfer");
rewardToken.transfer(msg.sender, value);
prevBalance = rewardToken.balanceOf(address(this));
return value;
}
function softWithdrawRewardFor(address forAddress) external returns (uint256){
updateTotalReward();
uint256 value = calcReward(forAddress);
rewardAtTimeOfWithdraw[forAddress] = totalReward;
owed[forAddress] += value;
return value;
}
function rewardFor(address forAddress) public view returns (uint256) {
uint256 _currentBalance = rewardToken.balanceOf(address(this));
uint256 _totalReward = totalReward +
(_currentBalance > prevBalance ? _currentBalance - prevBalance : 0);
return
owed[forAddress] +
(holderToken.balanceOf(forAddress) *
(_totalReward - rewardAtTimeOfWithdraw[forAddress])) /
holderToken.totalSupply();
}
function updateTotalReward() internal returns (uint256) {
uint256 currentBalance = rewardToken.balanceOf(address(this));
if (currentBalance > prevBalance) {
totalReward += currentBalance - prevBalance;
}
return totalReward;
}
function calcReward(address forAddress) internal view returns (uint256) {
return
(holderToken.balanceOf(forAddress) *
(totalReward - rewardAtTimeOfWithdraw[forAddress])) /
holderToken.totalSupply();
}
fallback() external {withdrawReward();}
}
文件 2 的 3:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, 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 from,
address to,
uint256 amount
) external returns (bool);
}
文件 3 的 3:SubDevFund.sol
pragma solidity 0.8.14;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./DevFund.sol";
contract SubDevFund {
IERC20 public rewardToken;
IERC20 public holderToken;
DevFund public mainDevFund;
uint256 public totalReward;
uint256 public prevBalance;
mapping(address => uint256) public rewardAtTimeOfWithdraw;
mapping(address => uint256) public owed;
constructor(address _rewardToken) {
rewardToken = IERC20(_rewardToken);
}
function setup(address _holderToken, address _mainDevFund) external returns (bool) {
require(address(holderToken) == address(0), "SubDevFund: already setup");
require(_holderToken != address(0), "SubDevFund: invalid _holderToken");
require(_mainDevFund != address(0), "SubDevFund: invalid _mainDevFund");
holderToken = IERC20(_holderToken);
mainDevFund = DevFund(_mainDevFund);
return true;
}
function withdrawFromMain() public {
mainDevFund.withdrawReward();
}
function withdrawReward() public returns (uint256) {
updateTotalReward();
uint256 value = calcReward(msg.sender) + owed[msg.sender];
rewardAtTimeOfWithdraw[msg.sender] = totalReward;
owed[msg.sender] = 0;
require(value > 0, "SubDevFund: withdrawReward nothing to transfer");
rewardToken.transfer(msg.sender, value);
prevBalance = rewardToken.balanceOf(address(this));
return value;
}
function softWithdrawRewardFor(address forAddress) external returns (uint256){
updateTotalReward();
uint256 value = calcReward(forAddress);
rewardAtTimeOfWithdraw[forAddress] = totalReward;
owed[forAddress] += value;
return value;
}
function rewardFor(address forAddress) public view returns (uint256) {
uint256 _currentBalance = rewardToken.balanceOf(address(this));
uint256 _totalReward = totalReward +
(_currentBalance > prevBalance ? _currentBalance - prevBalance : 0);
return
owed[forAddress] +
(holderToken.balanceOf(forAddress) *
(_totalReward - rewardAtTimeOfWithdraw[forAddress])) /
holderToken.totalSupply();
}
function updateTotalReward() internal returns (uint256) {
uint256 currentBalance = rewardToken.balanceOf(address(this));
if (currentBalance > prevBalance) {
totalReward += currentBalance - prevBalance;
}
return totalReward;
}
function calcReward(address forAddress) internal view returns (uint256) {
return
(holderToken.balanceOf(forAddress) *
(totalReward - rewardAtTimeOfWithdraw[forAddress])) /
holderToken.totalSupply();
}
fallback() external {withdrawReward();}
}
{
"compilationTarget": {
"contracts/SubDevFund.sol": "SubDevFund"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 2
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"holderToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainDevFund","outputs":[{"internalType":"contract DevFund","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"owed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prevBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardAtTimeOfWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forAddress","type":"address"}],"name":"rewardFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_holderToken","type":"address"},{"internalType":"address","name":"_mainDevFund","type":"address"}],"name":"setup","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"forAddress","type":"address"}],"name":"softWithdrawRewardFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawFromMain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]