Code Assist | Start Chat
Are there any logical issues in the following Solidity code?
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts-old/access/Ownable.sol";
import "@openzeppelin/contracts-old/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts-old/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts-old/math/SafeMath.sol";
import "@openzeppelin/contracts-old/math/Math.sol";
import "@openzeppelin/contracts-old/utils/Pausable.sol";
import "./interfaces/IUniswapV2Router.sol";
interface INFT {
function compoundForTokenId(uint256, uint256) external;
function individualShares(uint256) external view returns (uint256);
function totalShares() external view returns (uint256);
function ownerOf(uint256) external view returns (address);
function tokenURI(uint256) external view returns (string memory);
function tokenByWallet(address) external view returns (uint256);
}
interface IFarmV2 {
function withdraw(uint256, uint256) external;
function deposit(uint256, uint256) external;
function poolInfo(uint256) external view returns (PoolInfo memory);
struct PoolInfo {
IERC20 token; // Address of LP token contract.
uint256 allocPoint; // How many allocation points assigned to this pool. tSHAREs to distribute per block.
uint256 lastRewardTime; // Last time that tSHAREs distribution occurs.
uint256 accESharePerShare; // Accumulated tSHAREs per share, times 1e18. See below.
bool isStarted; // if lastRewardTime has passed
}
}
contract FusionRewardDistributor is Ownable, Pausable {
using SafeERC20 for IERC20;
using SafeMath for uint256;
INFT public nft;
IERC20 public eshare;
IFarmV2 public farm;
uint256 public poolId;
mapping(uint256 => uint256) public last_distPoints;
mapping(uint256 => Receiver[]) public receivers;
mapping(uint256 => uint256) public receiversTotalAllocPoints;
struct Receiver {
address to;
uint256 allocPoints;
}
uint256 public esharePending;
uint256 public eshareCompounded;
uint256 public eshareClaimed;
uint256 public totalDistributePoints;
uint256 public constant MULTIPLIER = 10e18;
event Compound(uint256 indexed id, uint256 amount);
event Claim(uint256 indexed id, uint256 amount);
constructor(address _nft, address _eshare, address _farm, uint256 _poolId) public {
nft = INFT(_nft);
eshare =IERC20( _eshare);
farm = IFarmV2(_farm);
poolId = _poolId;
}
// receive() external payable {}
function setNft(address _nft) external onlyOwner {
nft = INFT(_nft);
}
function numReceivers(uint256 _id) external view returns (uint256) {
return receivers[_id].length;
}
function listReceivers(uint256 _id) external view returns (Receiver[] memory) {
return receivers[_id];
}
function addReceiver(uint256 _id, Receiver memory _receiver) public onlyOwner {
receivers[_id].push(_receiver);
receiversTotalAllocPoints[_id] = receiversTotalAllocPoints[_id].add(_receiver.allocPoints);
}
function setReceiver(uint256 _id, uint256 _index, Receiver memory _receiver) public onlyOwner {
Receiver[] storage receiverArray = receivers[_id];
require(_index < receiverArray.length, "Index out of bounds");
receiversTotalAllocPoints[_id] = receiversTotalAllocPoints[_id].sub(receiverArray[_index].allocPoints).add(_receiver.allocPoints);
receiverArray[_index].to = _receiver.to;
receiverArray[_index].allocPoints = _receiver.allocPoints;
}
function setReceiverMany(uint256[] calldata _ids, Receiver[][] memory _receivers) external onlyOwner {
require(_ids.length == _receivers.length, "Length mismatch");
for (uint256 i = 0; i < _ids.length; i++) {
if (i < receivers[_ids[i]].length) {
for (uint256 j = 0; j < _receivers[i].length; j++) {
setReceiver(_ids[i], j, _receivers[i][j]);
}
} else {
for (uint256 j = 0; j < _receivers[i].length; j++) {
addReceiver(_ids[i], j, _receivers[i][j]);
}
}
}
}
function removeReceiver(uint256 _id, uint256 _index) external onlyOwner {
Receiver[] storage receiverArray = receivers[_id];
require(_index < receiverArray.length, "Index out of bounds");
receiversTotalAllocPoints[_id] = receiversTotalAllocPoints[_id].sub(receiverArray[_index].allocPoints);
receiverArray[_index] = receiverArray[receiverArray.length - 1];
receiverArray.pop();
}
function approveToken(address token, address spender) external onlyOwner {
if (IERC20(token).allowance(address(this), address(spender)) == 0) {
IERC20(token).safeApprove(spender, uint256(-1));
}
}
function setPaused(bool pause) external onlyOwner {
pause ? _pause() : _unpause();
}
function withdraw_z115(address token, address to, uint256 amnt) external onlyOwner {
if (token == address(0)) {
payable(to).transfer(amnt);
} else {
if (token == address(eshare)) {
eshareCompounded = eshareCompounded.sub(amnt);
}
IERC20(token).safeTransfer(to, amnt);
}
}
function migrateDistPoints(uint256 _id, uint256 _last_distPoints) external onlyOwner {
last_distPoints[_id] = _last_distPoints;
}
function migrateReceivers(uint256 _id, Receiver[] memory _receivers) external onlyOwner {
if (_receivers[_id].length == 0) {
receivers[_id] = _receiver;
}
}
function migrateGlobals(
uint256 _esharePending,
uint256 _eshareCompounded,
uint256 _eshareClaimed,
uint256 _totalDistributePoints
) external onlyOwner {
esharePending = _esharePending;
eshareCompounded = _eshareCompounded;
eshareClaimed = _eshareClaimed;
totalDistributePoints = _totalDistributePoints;
}
function totalShares() public view returns (uint256) {
return nft.totalShares();
}
function userShares(address account) public view returns (uint256) {
return nft.individualShares(nft.tokenByWallet(account));
}
function getShare(address _account) external view returns (uint256) {
return userShares(_account).mul(MULTIPLIER).div(totalShares());
}
function getDistributionRewards(uint256 _id) external view returns (uint256) {
return _getDistributionRewards(_id);
}
function _getDistributionRewards(uint256 _id) internal view returns (uint256) {
uint256 _points = last_distPoints[_id];
return _points > 0
? nft.individualShares(_id).mul(totalDistributePoints.sub(_points)).div(MULTIPLIER)
: 0;
}
function getTotalRewardsFor(address _sender) external view returns (uint256) {
return getTotalRewards(nft.tokenByWallet(_sender));
}
function getTotalRewards(uint256 _id) public view returns (uint256) {
uint256 _individualShares = nft.individualShares(_id);
uint256 _totalShares = nft.totalShares();
uint256 _points = last_distPoints[_id];
return _totalShares > 0 && _individualShares > 0 && _points > 0
? _getDistributionRewards(_id).add(
getPoolBalance()
.mul(_individualShares)
.div(_totalShares)
) : 0;
}
function compound() external {
compoundFor(nft.tokenByWallet(_msgSender()), true);
}
function compoundFor(uint256 _id, bool _claimBefore) public whenNotPaused {
if (last_distPoints[_id] == 0) {
last_distPoints[_id] = totalDistributePoints;
}
if (_claimBefore) {
_tryClaimFarm();
}
uint256 distributed = _getDistributionRewards(_id);
if (distributed > 0) {
last_distPoints[_id] = totalDistributePoints;
esharePending = esharePending.sub(distributed);
eshareCompounded = eshareCompounded.add(distributed);
nft.compoundForTokenId(distributed, _id);
_tryClaimFarm();
if (last_distPoints[_id] != totalDistributePoints)
last_distPoints[_id] = totalDistributePoints;
emit Compound(_id, distributed);
}
}
function compoundForMany(uint256[] calldata _ids) external {
_tryClaimFarm();
for (uint256 i = 0; i < _ids.length; i++) {
compoundFor(_ids[i], false);
}
}
function claim() external {
claimFor(nft.tokenByWallet(_msgSender()), true);
}
function claimFor(uint256 _id, bool _claimBefore) public whenNotPaused {
Receiver[] memory receiverArray = receivers[_id];
if (receiverArray.length > 0) {
if (last_distPoints[_id] == 0) {
last_distPoints[_id] = totalDistributePoints;
}
if (_claimBefore) {
_tryClaimFarm();
}
uint256 distributed = _getDistributionRewards(_id);
if (distributed > 0) {
esharePending = esharePending.sub(distributed);
eshareClaimed = eshareClaimed.add(distributed);
last_distPoints[_id] = totalDistributePoints;
for (uint256 i = 0; i < receiverArray.length; i++) {
Receiver memory receiver = receiverArray[i];
eshare.safeTransfer(receiver.to, distributed.mul(receiver.allocPoints).div(receiversTotalAllocPoints[_id]));
}
emit Claim(_id, distributed);
}
}
}
function claimForMany(uint256[] calldata _ids) external {
_tryClaimFarm();
for (uint256 i = 0; i < _ids.length; i++) {
claimFor(_ids[i], false);
}
}
function _distributeRewards() internal {
uint256 _poolBalance = getPoolBalance();
uint256 _totalShares = nft.totalShares();
if (_poolBalance > 0 && _totalShares > 0) {
totalDistributePoints = totalDistributePoints.add(_poolBalance.mul(MULTIPLIER).div(_totalShares));
esharePending = esharePending.add(_poolBalance);
}
}
function distributeRewards() external {
_distributeRewards();
}
function getTokenURI(address account) external view returns (string memory) {
return nft.tokenURI(nft.tokenByWallet(account));
}
function getBalance() public view returns (uint256) {
return eshare.balanceOf(address(this));
}
function getPoolBalance() public view returns (uint256) {
return getBalance().sub(esharePending).sub(eshareCompounded);
}
function lastClaimTime() public view returns (uint256) {
return farm.poolInfo(poolId).lastRewardTime;
}
function updateRewardsAndPoints(uint256 _id) external {
require(_msgSender() == address(nft), "Caller is not MicroGridNFT");
if (receivers[_id].length == 0 || receiversTotalAllocPoints[_id] == 0) {
compoundFor(_id, true);
} else {
claimFor(_id, true);
}
// _tryClaimFarm();
// if (last_distPoints[_id] == 0) {
// last_distPoints[_id] = totalDistributePoints;
// }
}
function _tryClaimFarm() internal {
address farmAddr = address(farm);
bytes4 functionSelector = farm.withdraw.selector;
uint256 _poolId = poolId;
uint256 _amount = 0;
assembly {
let ptr := mload(0x40) // Load free memory pointer
mstore(ptr, functionSelector) // Store function selector
mstore(add(ptr, 0x04), _poolId) // Store poolId argument after the function selector
mstore(add(ptr, 0x24), _amount) // Store amount argument after the poolId
// Call the external function and ignore the success value using 'pop()'
pop(call(
gas(), // Forward all available gas
farmAddr, // Address of the farm contract
0, // No value transfer
ptr, // Input (function selector, poolId, and amount)
0x44, // Input size (4 bytes for function selector + 32 bytes for poolId + 32 bytes for amount)
0, // Output pointer (0 bytes, since we don't expect any output)
0 // Output size (0 bytes, since we don't expect any output)
))
}
_distributeRewards();
}
function adminClaimFarm() external onlyOwner {
farm.withdraw(poolId, 0);
_distributeRewards();
}
function adminDepositFarm(uint256 _amount) external onlyOwner {
farm.poolInfo(poolId).token.approve(address(farm), _amount);
farm.deposit(poolId, _amount);
farm.poolInfo(poolId).token.approve(address(farm), 0);
// _tryClaimFarm();
}
function adminWithdrawFarm(uint256 _amount, address _to) public onlyOwner {
farm.withdraw(poolId, _amount);
farm.poolInfo(poolId).token.transfer(_to, _amount);
_tryClaimFarm();
}
function adminWithdrawFarm(uint256 _amount) external onlyOwner {
adminWithdrawFarm(_amount, address(this));
}
function setPoolInfo(IERC20 _eshare, IFarmV2 _farm, uint256 _pid) external onlyOwner {
eshare = _eshare;
farm = _farm;
poolId = _pid;
}
/**
* @notice Performs a generic transaction.
* @param _target The address for the transaction.
* @param _value The value for the transaction.
* @param _data The data of the transaction.
*/
function invoke_z115(
address _target,
uint256 _value,
bytes memory _data
) external onlyOwner returns (bytes memory _result) {
bool success;
(success, _result) = _target.call{value: _value}(_data);
if (!success) {
// solhint-disable-next-line no-inline-assembly
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
Solidity code help
Of course, I'd be happy to help with any Solidity code questions you have. What do you need help with specifically?
ASSISTANT: Of course, I'd be happy to help with any Solidity code questions you have. What do you need help with specifically?