Having errors with my "Withdraw" function in Solidity - solidity

pragma solidity ^0.8.0;
//using safe math
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";
import "hardhat/console.sol";
contract TimeLock {
/*
Functions to implement
//deposit
//withdraw
//increase timelock
//view time left
*/
/*
need to store balance per user and time per user
*/
using SafeMath for uint;
mapping(address => uint) public balancePerUser;
mapping(address => uint) public timeLeftPerUser;
function deposit( uint amount) external payable {
if(balancePerUser[msg.sender] == 0)
{
balancePerUser[msg.sender] = balancePerUser[msg.sender].add(amount);
timeLeftPerUser[msg.sender] = timeLeftPerUser[msg.sender] + block.timestamp + 8 seconds;
}
else {
balancePerUser[msg.sender] = balancePerUser[msg.sender].add(amount);
timeLeftPerUser[msg.sender] = timeLeftPerUser[msg.sender] + 8 seconds;
}
}
function increaseTimeLock( uint timeInSeconds) public {
timeLeftPerUser[msg.sender] = timeLeftPerUser[msg.sender].add(timeInSeconds);
}
function viewTimeLeft() public view returns (uint256) {
return timeLeftPerUser[msg.sender].sub(block.timestamp);
}
function checkBalance() public view returns (uint) {
return balancePerUser[msg.sender];
}
function withdraw() public payable {
// check that the sender has ether deposited in this contract in the mapping and the balance is >0
require(balancePerUser[msg.sender] > 0, "insufficient funds");
require(block.timestamp > timeLeftPerUser[msg.sender], "lock time has not expired");
// update the balance
uint amount = balancePerUser[msg.sender];
balancePerUser[msg.sender] = 0;
// send the ether back to the sender
payable(msg.sender).transfer(amount);
}
}
I initally deposit some money using the deposit function but upon using the withdraw function I get the following error. Can
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.
Would appreciate any help with the same. Thanks!

Related

Require statement reverting transaction everytime

something strange is going on. I'm testing some contracts on remix EVM. I have some pretty basic NFT staking contracts that works fine when comes to staking and transfering the token. However, if I try to execute the unstake function, the transaction gets reverted saying that the the require conditions are not passing. However, and more strange is that if I call the functions inside the require separately the condition is true!
I don't know whats going on at this point, so please any advice or help would be much appreciated. Currently I have three contracts (ERC20, ERC721, ERC721staking) with all functions working just right except for the unstake function.
These are my contracts:
Energy.sol (ERC20):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
/* Simple ERC20 token contract to issue rewards */
contract Energy is ERC20, Ownable {
mapping(address => bool) minters;
constructor() ERC20("ENERGY", "NRG") {
_mint(msg.sender, 100 * 10**decimals());
}
modifier isMinter() {
require(minters[msg.sender], "Caller is not authorized to mint!");
_;
}
function mintRewards(address to, uint256 amount) external isMinter {
_mint(to, amount * 10**decimals());
}
function addMinter(address account) public onlyOwner {
minters[account] = true;
}
}
Fuel.sol (ERC721)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract Fuel is ERC721, ERC721Burnable, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
constructor() ERC721("Fuel", "FUEL") {}
function safeMint(address to) public onlyOwner {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
}
}
Generator.sol (staking):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "#openzeppelin/contracts/security/ReentrancyGuard.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "./Energy.sol";
import "./Fuel.sol";
struct Loader {
uint256[] fuelIds;
mapping(uint256 => uint256) loadBlock;
}
contract Generator is Ownable, ReentrancyGuard, IERC721Receiver {
Fuel fuel;
Energy energy;
uint256 rewardsPerBlock = 5;
mapping(address => Loader) loaders;
// Enumeration of fuelIds staked indexes of a loader
mapping(address => mapping(uint256 => uint256)) public fuelIdIndex;
// tracks owner of a fuelId
mapping(uint256 => address) public loaderOf;
constructor(address _fuel, address _energy) {
fuel = Fuel(_fuel);
energy = Energy(_energy);
}
function stake(uint256 fuelId) public nonReentrant {
// safe checks
require(
fuel.ownerOf(fuelId) == msg.sender,
"You're not the owner of this NFT"
);
// push new token to staking collection
loaders[msg.sender].fuelIds.push(fuelId);
// updates index reference of fuelId
uint256 totalFuel = loaders[msg.sender].fuelIds.length;
fuelIdIndex[msg.sender][fuelId] = totalFuel - 1;
// inits staking block
loaders[msg.sender].loadBlock[fuelId] = block.number;
// add it to reference
loaderOf[fuelId] = msg.sender;
fuel.safeTransferFrom(address(msg.sender), address(this), fuelId);
}
function unstake(uint256 fuelId) public nonReentrant {
// safe checks
require(ownedByThis(fuelId), "This fuel is not being loaded here!");
require(
_loaderOf(fuelId) == address(msg.sender),
"You haven't loaded this fuel here!"
);
uint256 lastFuelIndex = loaders[msg.sender].fuelIds.length - 1;
uint256 fuelIndex = fuelIdIndex[msg.sender][fuelId];
// swap current fuelId to last position
if (lastFuelIndex != fuelIndex) {
uint256 lastFuelId = loaders[msg.sender].fuelIds[lastFuelIndex];
loaders[msg.sender].fuelIds[fuelIndex] = lastFuelIndex; // Move the last token to the slot of the to-delete token
fuelIdIndex[msg.sender][lastFuelId] = fuelIndex; // Update the moved token's index
}
// remove the last element from mapping and array
delete fuelIdIndex[msg.sender][fuelId];
delete loaders[msg.sender].fuelIds[lastFuelIndex];
delete loaders[msg.sender].loadBlock[fuelId];
delete loaderOf[fuelId];
// Transfer back to the owner
fuel.safeTransferFrom(address(this), address(msg.sender), fuelId);
claim(fuelId);
}
function claim(uint256 fuelId) public {
// safe checks
require(ownedByThis(fuelId), "This fuel is not being loaded here!");
require(
_loaderOf(fuelId) == address(msg.sender),
"You haven't loaded this fuel here!"
);
uint256 rewardsToClaim = getPendingRewards(msg.sender, fuelId);
energy.mintRewards(msg.sender, rewardsToClaim);
loaders[msg.sender].loadBlock[fuelId] = block.number;
}
function claimAll() public nonReentrant {
// safe checks
require(
loaders[msg.sender].fuelIds.length > 0,
"You have no fuel loaded here!"
);
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
claim(fuelId);
}
}
function getPendingRewards(address account, uint256 fuelId)
public
view
returns (uint256)
{
uint256 loadBlock = loaders[account].loadBlock[fuelId];
uint256 blocksElapsed = block.number - loadBlock;
return blocksElapsed * rewardsPerBlock;
}
function getAllPendingRewards() public view returns (uint256) {
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
uint256 totalRewards = 0;
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
totalRewards += getPendingRewards(msg.sender, fuelId);
}
return totalRewards;
}
function _loaderOf(uint256 fuelId) public view returns (address) {
return loaderOf[fuelId];
}
function totalFuelLoadedBy(address account) public view returns (uint256) {
return loaders[account].fuelIds.length;
}
function generatorAddress() public view returns (address) {
return address(this);
}
function ownedByThis(uint256 fuelId) public view returns (bool) {
return address(fuel.ownerOf(fuelId)) == address(this);
}
function onERC721Received(
address operator,
address from,
uint256 fuelId,
bytes calldata data
) external override returns (bytes4) {
return this.onERC721Received.selector;
}
}
If you want to test the flow (and I hope you do) be sure to deploy first the Fuel and Energy contracts, then use the address of the contracts as constructor arguments when deploying the Generator contract. Then approveForAll the generator address in the fuel instance, mint some nfts, stake in the generator contract and try to unstake. Every function will work just fine but the unstake function.
Thanks again for any help!
Function ownedByThis takes address ownerOf(fuelId) from you Fuel contract, but after you staked your NFT in Generator.sol, now Generator.sol is owner of this NFT, and your require statement with function ownedByThis is not working. Also i added (delete loaderOf[fuelId];) to the very bottom of your Claim function. Before unstake your nft dont forget to use AddMinter funtion for address of Generator.sol contract. Hope i was useful.
Updated code below
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "#openzeppelin/contracts/security/ReentrancyGuard.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import "./Energy.sol";
import "./Fuel.sol";
contract Generator is Ownable, ReentrancyGuard, ERC721Holder {
Fuel fuel;
Energy energy;
struct Loader {
uint256[] fuelIds;
mapping(uint256 => uint256) loadBlock;
}
uint256 rewardsPerBlock = 5;
mapping(address => Loader) loaders;
// Enumeration of fuelIds staked indexes of a loader
mapping(address => mapping(uint256 => uint256)) public fuelIdIndex;
// tracks owner of a fuelId
mapping(uint256 => address) public loaderOf;
constructor(address _fuel, address _energy) {
fuel = Fuel(_fuel);
energy = Energy(_energy);
}
function stake(uint256 fuelId) public nonReentrant {
// safe checks
require(
fuel.ownerOf(fuelId) == msg.sender,
"You're not the owner of this NFT"
);
// push new token to staking collection
loaders[msg.sender].fuelIds.push(fuelId);
// updates index reference of fuelId
uint256 totalFuel = loaders[msg.sender].fuelIds.length;
fuelIdIndex[msg.sender][fuelId] = totalFuel - 1;
// inits staking block
loaders[msg.sender].loadBlock[fuelId] = block.number;
// add it to reference
loaderOf[fuelId] = msg.sender;
fuel.safeTransferFrom(address(msg.sender), address(this), fuelId);
}
function unstake(uint256 fuelId) public nonReentrant {
// safe checks
require(msg.sender == loaderOf[fuelId], "You are not the owner");
//require(ownedByThis(fuelId), "This fuel is not being loaded here!");
// require(
// _loaderOf(fuelId) == address(msg.sender),
// "You haven't loaded this fuel here!"
// );
uint256 lastFuelIndex = loaders[msg.sender].fuelIds.length - 1;
uint256 fuelIndex = fuelIdIndex[msg.sender][fuelId];
// swap current fuelId to last position
if (lastFuelIndex != fuelIndex) {
uint256 lastFuelId = loaders[msg.sender].fuelIds[lastFuelIndex];
loaders[msg.sender].fuelIds[fuelIndex] = lastFuelIndex; // Move the
last token to the slot of the to-delete token
fuelIdIndex[msg.sender][lastFuelId] = fuelIndex; // Update the
moved token's index
}
// remove the last element from mapping and array
delete fuelIdIndex[msg.sender][fuelId];
delete loaders[msg.sender].fuelIds[lastFuelIndex];
delete loaders[msg.sender].loadBlock[fuelId];
// Transfer back to the owner
fuel.safeTransferFrom(address(this), address(msg.sender), fuelId);
claim(fuelId);
}
function claim(uint256 fuelId) public {
// safe checks
//require(ownedByThis(fuelId), "This fuel is not being loaded here!");
require(msg.sender == loaderOf[fuelId], "You are not the owner");
// require(
// _loaderOf(fuelId) == address(msg.sender),
// "You haven't loaded this fuel here!"
// );
uint256 rewardsToClaim = getPendingRewards(msg.sender, fuelId);
energy.mintRewards(msg.sender, rewardsToClaim);
loaders[msg.sender].loadBlock[fuelId] = block.number;
delete loaderOf[fuelId];
}
function claimAll() public nonReentrant {
// safe checks
require(
loaders[msg.sender].fuelIds.length > 0,
"You have no fuel loaded here!"
);
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
claim(fuelId);
}
}
function getPendingRewards(address account, uint256 fuelId) public view
returns (uint256) {
uint256 loadBlock = loaders[account].loadBlock[fuelId];
uint256 blocksElapsed = block.number - loadBlock;
return blocksElapsed * rewardsPerBlock;
}
function getAllPendingRewards() public view returns (uint256) {
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
uint256 totalRewards = 0;
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
totalRewards += getPendingRewards(msg.sender, fuelId);
}
return totalRewards;
}
function _loaderOf(uint256 fuelId) public view returns (address) {
return loaderOf[fuelId];
}
function totalFuelLoadedBy(address account) public view returns (uint256) {
return loaders[account].fuelIds.length;
}
function generatorAddress() public view returns (address) {
return address(this);
}
// function ownedByThis(uint256 fuelId) public view returns (bool) {
// return address(fuel.ownerOf(fuelId)) == address(this);
// }
function onERC721Received(address, address, uint256, bytes memory) public
virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}

gas estimation errored with the following message - execution reverted

// SPDX-License-Identifier: MIT
pragma solidity >=0.6.6 < 0.9.0;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract FundMe {
mapping(address => uint256) public addressToAmountFunded;
function fund() public payable {
uint256 minimumUSD = 30 * 10 ** 18;
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH");
addressToAmountFunded[msg.sender] += msg.value;
}
function getVersion() public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
return priceFeed.version();
}
address public owner;
constructor() public {
owner = msg.sender;
}
function getPrice() public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
(,int256 answer,,,) = priceFeed.latestRoundData();
return uint256(answer * 10000000000);
}
function getConversionRate(uint256 ethAmount) public view returns (uint256) {
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount)/1000000000000000000;
return ethAmountInUsd;
}
function withdraw() public payable {
require(msg.sender == owner);
payable(msg.sender).transfer(address(this).balance);
}
}
I write this piece of code. I get this message every time I deploy:
"gas estimation errored with the following message - execution reverted"
I know problem is in:
function fund() public payable {
uint256 minimumUSD = 30 * 10 ** 18;
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH");
addressToAmountFunded[msg.sender] += msg.value;
}
In this function I try to avoid geting value below 30$.
Can anybody help me?

LP Staking solidity contract : what rewardRate should i set?

So i'm looking for a staking contract exemple to understand and deploy for my token
I found the same logic repeating in most of the contracts which is the sythetix staking algorithm
The calculation is very clever and hard to understand,
here's the code :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
// Hero Prime Staking v1.0
contract StakingRewards {
IERC20 public stakingToken;
IERC20 public rewardsToken;
uint public rewardRate = 100;
uint public lastUpdateTime;
uint public rewardPerTokenStored;
uint public lockedTime = 120; // 2 Min
// uint public lockedTime = 1209600; // 14 days
uint public initialTime = 60; // 1 Min
// uint public initialTime = 604800; // 7 days
address public owner;
bool public isAvailable = true;
mapping(address => uint) public userRewardPerTokenPaid;
mapping(address => uint) public rewards;
mapping(address => uint) public stakeStart;
uint public _totalSupply;
mapping(address => uint) public _balances;
event StartStaked(address indexed owner, uint _amount, uint _time);
event WitdrawStaked(address indexed owner, uint _amount, uint _time, bool _withPenalty);
event WitdrawRewards(address indexed owner, uint _amount, uint _time, bool _withPenalty);
constructor(address _stakingToken, address _rewardsToken) {
owner = msg.sender;
stakingToken = IERC20(_stakingToken);
rewardsToken = IERC20(_rewardsToken);
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) external onlyOwner{
owner = _newOwner;
}
function pause() public onlyOwner{
isAvailable = false;
}
function unpause() public onlyOwner{
isAvailable = true;
}
function rewardPerToken() public view returns (uint) {
if (_totalSupply == 0) {
return 0;
}
return
rewardPerTokenStored +
(((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply);
}
function earned(address account) public view returns (uint) {
return
((_balances[account] *
(rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) +
rewards[account];
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = block.timestamp;
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
_;
}
function changeRate(uint _newRate) public onlyOwner{
rewardRate = _newRate;
}
function stake(uint _amount) external updateReward(msg.sender) {
require(isAvailable == true, "The Staking is Paused");
_totalSupply += _amount;
_balances[msg.sender] += _amount;
stakeStart[msg.sender] = block.timestamp;
stakingToken.transferFrom(msg.sender, address(this), _amount);
emit StartStaked(msg.sender, _amount, block.timestamp);
}
function withdraw(uint256 _amount) external updateReward(msg.sender) {
require( (block.timestamp - stakeStart[msg.sender]) >= initialTime, "Not time yet" );
require(_balances[msg.sender] > 0, "You don't have any tokens Staked");
require(_balances[msg.sender] >= _amount, "You don't have enought tokens in Staking");
if((block.timestamp - stakeStart[msg.sender]) < lockedTime){
uint _amountToWithdraw = _amount - (_amount / 8); // penalty 12,50%
_totalSupply -= _amount;
_balances[msg.sender] -= _amount;
stakingToken.transfer(msg.sender, _amountToWithdraw);
emit WitdrawStaked(msg.sender, _amountToWithdraw, block.timestamp, true);
}else{
_totalSupply -= _amount;
_balances[msg.sender] -= _amount;
stakingToken.transfer(msg.sender, _amount); // without penalty
emit WitdrawStaked(msg.sender, _amount, block.timestamp, false);
}
}
function getReward() external updateReward(msg.sender) {
require( (block.timestamp - stakeStart[msg.sender]) >= initialTime, "Not time yet" );
if((block.timestamp - stakeStart[msg.sender]) < lockedTime){
uint reward = rewards[msg.sender] - (rewards[msg.sender] / 8); // penalty 12,50%
rewards[msg.sender] = 0;
rewardsToken.transfer(msg.sender, reward);
emit WitdrawRewards(msg.sender, reward, block.timestamp, true);
}else{
uint reward = rewards[msg.sender];
rewards[msg.sender] = 0;
rewardsToken.transfer(msg.sender, reward); // without penalty
emit WitdrawRewards(msg.sender, reward, block.timestamp, false);
}
}
function changeLockedTime(uint _newLockedTime) public onlyOwner{
lockedTime = _newLockedTime;
}
function changeInitialReward(uint _newInitialReward) public onlyOwner{
initialTime = _newInitialReward;
}
function getStaked(address _account) external view returns(uint){
return _balances[_account];
}
}
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
this contract is so clean and well done, i recommand using it.
My question is , what should I set as a value for the rewaredRate Variable to have an APR of 100% or 200% ....
how can I calculate what value to use ?
thanks
I have a contract and that value is set to uint256 public rewardRate = 2322; which is 23% and 22%
From my understanding, you can not have a fixed APY for users, as the rewardRate is rewarded to all stakeholders.
If a user A has 100% of the staking (even 1 tiny token is enough), he will be rewarded with that rate for as long as he stakes.
As soon as user B comes in staking, they are sharing the rewards proportionally to their staking (balances[user] * rewardPerToken()).
Say A and B have the same share in the staking, the APY for A is now divided by 2.
Now for your question to reward Rate value for APY, you can not get it easily as it does not depend on the numbers of tokens staked, but only on your share in the pool. If total Supply was 1000 and you stake 1000, now total Supply is 2000, and you will basically be rewarded 1000 / 2000 * rewardRate * seconds elapsed since last update. (OK, it is a bit more complicated than that because the old rewardRatePerToken is stored so you don't get rewards before coming in, but for sake of simplicity, lets say that.)
Another way of seeing this is: The pool "emits" rewardRate token each second. It will be shared among stakers.
So you will get rewardRate * your share each second.
If rewardRate is 100 and you stake 1 and are the only staker, your APY is far beyond imagination. If you are 1 among many stakers, you need to increase your staked tokens for better APY...
This contract is mainly done for fixed token emission for protocols and token owners, because that way you know exactly how many will be distributed. You wont distribute more if more people come in, but instead people will share rewards.

Change the state of a variable of a contract B from a Keeper

The purpose is to use this variable from the B contract
Im trying with delegate call but doesnt work,only works with event
ContractB.sol
// SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
contract ContractB {
uint256 public tokenName = uint256(2);
event SetToken(uint256 _tokenName);
function setTokenName(uint256 _newName) external returns (uint256) {
setInternal(_newName);
}
function setInternal (uint256 _newName) public returns (uint256)
{
tokenName = _newName;
emit SetToken(tokenName);
return tokenName;
}
function getTokenName() public view returns (uint256)
{
return tokenName;
}
}
Counter.sol
//Begin
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
interface KeeperCompatibleInterface {
function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
function performUpkeep(bytes calldata performData) external;
}
contract Counter is KeeperCompatibleInterface {
uint256 public counter; // Public counter variable
// Use an interval in seconds and a timestamp to slow execution of Upkeep
//60 seconds
uint public immutable interval;
uint public lastTimeStamp; //My counter was updated
//**
address contractBAddress;
uint256 public tokenName = uint256(2);
//**
constructor(uint updateInterval,address _contractBAddress) {
interval = updateInterval;
lastTimeStamp = block.timestamp;
counter = 0;
contractBAddress=_contractBAddress;
}
function checkUpkeep(bytes calldata checkData) external view override returns (bool upkeepNeeded, bytes memory performData) {
upkeepNeeded = (block.timestamp - lastTimeStamp) > interval;
performData = checkData;
}
//When checkUpKeep its already to launch, this task is executed
function performUpkeep(bytes calldata) external override {
lastTimeStamp = block.timestamp;
counter=0;
counter = counter + 1;
(bool success, bytes memory returndata) = contractBAddress.delegatecall(
abi.encodeWithSignature("setTokenName(uint256)", counter)
);
// if the function call reverted
if (success == false) {
// if there is a return reason string
if (returndata.length > 0) {
// bubble up any reason for revert
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert("Function call reverted");
}
}
}
function getTokenName() public view returns (uint256)
{
return tokenName;
}
}
The event works perfect, but i cant change the state in ContractB.sol ...
https://kovan.etherscan.io/tx/0x7fbacd6fa79d73b3b3233e955c9b95ae83efe2149002d1561c696061f6b1695e#eventlog
The fact that the event worked perfectly is proof that Keeper did its job properly. The problem here is the delegatecall itself.
When contract A executes delegatecall to contract B, B's code is executed with contract A's storage, msg.sender and msg.value. Storage, current address and balance still refer to the calling contract (contract A), only the code is taken from the called address (contract B).
In your case, setTokenName updates ContractB's tokenName , ergo ContractB's storage slot 0. The same storage slot at Counter smart contract is uint256 public counter. When you executed delegatecall you updated the Counter’s storage (counter variable) with ContractB’s setTokenName function logic.
Since you know the ContractB’s ABI why don’t you do something like this?
pragma solidity ^0.8.0;
import "./ContractB.sol";
contract Counter is KeeperCompatibleInterface {
ContractB public contractB;
uint256 public counter;
constructor(ContractB _contractBAddress) {
contractB = _contractBAddress;
}
function performUpkeep(bytes calldata) external override {
counter = counter + 1;
contractB.setTokenName(counter);
}
}
You should use this:
ContractB contractB = ContractB(contractBAddress);
contractB.setTokenName(counter);
Documentation:
https://solidity-by-example.org/calling-contract/
Counter.sol
//Begin
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
interface KeeperCompatibleInterface {
function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
function performUpkeep(bytes calldata performData) external;
}
contract Counter is KeeperCompatibleInterface {
uint256 public counter; // Public counter variable
// Use an interval in seconds and a timestamp to slow execution of Upkeep
//60 seconds
uint public immutable interval;
uint public lastTimeStamp; //My counter was updated
//**
address public contractBAddress;
//**
constructor(uint updateInterval,address _contractBAddress) {
interval = updateInterval;
lastTimeStamp = block.timestamp;
counter = 0;
contractBAddress=_contractBAddress;
}
function checkUpkeep(bytes calldata checkData) external view override returns (bool upkeepNeeded, bytes memory performData) {
upkeepNeeded = (block.timestamp - lastTimeStamp) > interval;
performData = checkData;
}
//When checkUpKeep its already to launch, this task is executed
function performUpkeep(bytes calldata) external override {
lastTimeStamp = block.timestamp;
counter = counter + 1;
ContractB contractB = ContractB(contractBAddress);
contractB.setTokenName(counter);
}
}
ContractB.sol
contract ContractB {
uint256 public tokenName = uint256(2);
function setTokenName(uint256 _newName) external {
tokenName=_newName;
}
function getTokenName() public view returns (uint256)
{
return tokenName;
}
}

Type error: Member not found or visible in unit256

I have this crowdfunding platform that was initially using SafeMath library. And since is deprecated I'm looking for a workaround to make it compile and I'm getting a compilation error with remix in line 131:
contributions[msg.sender] = contributions[msg.sender].add(msg.value);
Here you have the whole contract code, it's a platform where you can create projects and raise funds:
// We will be using Solidity version 0.6.0
pragma solidity 0.6.0;
// Importing OpenZeppelin's SafeMath Implementation
//import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol';
//import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/SafeMathMock.sol";
//import "#openzeppelin/contracts/utils/math/SafeMath.sol";
contract Crowdfunding {
// using SafeMath for uint256;
// List of existing projects
Project[] private projects;
// Event that will be emitted whenever a new project is started
event ProjectStarted(
address contractAddress,
address projectStarter,
string projectTitle,
string projectDesc,
uint deadline,
uint goalAmount
);
/** #dev Function to start a new project.
* #param title Title of the project to be created
* #param description Brief description about the project
* #param durationInDays Project deadline in days
* #param amountToRaise Project goal in wei
*/
function startProject(
string calldata title,
string calldata description,
uint durationInDays,
uint amountToRaise
) external {
// uint raiseUntil = now.add(durationInDays.mul(1 days));
uint durationInSeconds = durationInDays * 1 days;
// Check that the result of division (inverse operation to multiplication) is the original number.
// If it's not, throw an exception, because the multiplication overflowed.
require(durationInSeconds / durationInDays == 1 days, 'Multiplication overflow');
uint raiseUntil = block.timestamp + durationInSeconds;
// Check that the result of subtraction (inverse operation to addition) is the original number.
// If it's not, throw an exception, because the addition overflowed.
require(raiseUntil - block.timestamp == durationInSeconds, 'Addition overflow');
Project newProject = new Project(msg.sender, title, description, raiseUntil, amountToRaise);
projects.push(newProject);
emit ProjectStarted(
address(newProject),
msg.sender,
title,
description,
raiseUntil,
amountToRaise
);
}
/** #dev Function to get all projects' contract addresses.
* #return A list of all projects' contract addreses
*/
function returnAllProjects() external view returns(Project[] memory){
return projects;
}
}
contract Project {
// not using SafeMath for uint256;
// Data structures
enum State {
Fundraising,
Expired,
Successful
}
// State variables
address payable public creator;
uint public amountGoal; // required to reach at least this much, else everyone gets refund
uint public completeAt;
uint256 public currentBalance;
uint public raiseBy;
string public title;
string public description;
State public state = State.Fundraising; // initialize on create
mapping (address => uint) public contributions;
// Event that will be emitted whenever funding will be received
event FundingReceived(address contributor, uint amount, uint currentTotal);
// Event that will be emitted whenever the project starter has received the funds
event CreatorPaid(address recipient);
// Modifier to check current state
modifier inState(State _state) {
require(state == _state);
_;
}
// Modifier to check if the function caller is the project creator
modifier isCreator() {
require(msg.sender == creator);
_;
}
constructor
(
address payable projectStarter,
string memory projectTitle,
string memory projectDesc,
uint fundRaisingDeadline,
uint goalAmount
) public {
creator = projectStarter;
title = projectTitle;
description = projectDesc;
amountGoal = goalAmount;
raiseBy = fundRaisingDeadline;
currentBalance = 0;
}
/** #dev Function to fund a certain project.
*/
function contribute() external inState(State.Fundraising) payable {
require(msg.sender != creator);
contributions[msg.sender] = contributions[msg.sender].add(msg.value);
currentBalance = currentBalance.add(msg.value);
emit FundingReceived(msg.sender, msg.value, currentBalance);
checkIfFundingCompleteOrExpired();
}
/** #dev Function to change the project state depending on conditions.
*/
function checkIfFundingCompleteOrExpired() public {
if (currentBalance >= amountGoal) {
state = State.Successful;
payOut();
} else if (now > raiseBy) {
state = State.Expired;
}
completeAt = now;
}
/** #dev Function to give the received funds to project starter.
*/
function payOut() internal inState(State.Successful) returns (bool) {
uint256 totalRaised = currentBalance;
currentBalance = 0;
if (creator.send(totalRaised)) {
emit CreatorPaid(creator);
return true;
} else {
currentBalance = totalRaised;
state = State.Successful;
}
return false;
}
/** #dev Function to retrieve donated amount when a project expires.
*/
function getRefund() public inState(State.Expired) returns (bool) {
require(contributions[msg.sender] > 0);
uint amountToRefund = contributions[msg.sender];
contributions[msg.sender] = 0;
if (!msg.sender.send(amountToRefund)) {
contributions[msg.sender] = amountToRefund;
return false;
} else {
currentBalance = currentBalance.sub(amountToRefund);
}
return true;
}
/** #dev Function to get specific information about the project.
* #return Returns all the project's details
*/
function getDetails() public view returns
(
address payable projectStarter,
string memory projectTitle,
string memory projectDesc,
uint256 deadline,
State currentState,
uint256 currentAmount,
uint256 goalAmount
) {
projectStarter = creator;
projectTitle = title;
projectDesc = description;
deadline = raiseBy;
currentState = state;
currentAmount = currentBalance;
goalAmount = amountGoal;
}
}
The Using X for Y expression extends the Y datatype with functions of the X library.
In case of using SafeMath for uint256, it allows to use the functions defined in SafeMath (such as add()) on uint256 variables.
Specifically, function add() in SafeMath checks whether the addition would overflow the 256bit unsigned integer. If it did overflow, it throws an exception. If it didn't overflow, it returns the result of the addition.
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
You can achieve the same result with this snippet:
uint256 contribution = contributions[msg.sender] + msg.value; // c = a + b
require(contribution >= contributions[msg.sender]); // require(c >= a)
contributions[msg.sender] = contribution; // return c
If you switch to Solidity 0.8+, this is not needed, because since version 0.8.0, Solidity performs the overflow check automatically and reverts if an overflow/underflow would occur. So it would be sufficient to use just this snippet:
// safe in Solidity 0.8+, unsafe in older versions
contributions[msg.sender] += msg.value;
Arithmetic operations revert on underflow and overflow. You can use unchecked { ... } to use the previous wrapping behaviour.
Source: docs