Need some help resolving smart contract warnings - solidity

New solidity programmer here.
I'm trying to create a smart contract where a user can create a Bounty. The creator sets the bounty on the smart contract in the constructor. They can subsequently choose the recipient of the funds after evaluation of some criteria. They can cancel, increase the bounty.
I tested the code out and it appears to work, but I'm getting some warnings in remix IDE that I don't know how to fix.
Could some one show me how its supposed to be done?
contract Bounty {
address payable public owner;
address payable public provider;
uint256 private bounty;
bool isActive;
event IncreaseBounty (uint256 oldBounty, uint256 newBounty);
event Paid(address owner, address payee, uint256 amount);
event Cancel(address owner, uint256 amount);
constructor() payable {
owner = payable(msg.sender);
bounty = msg.value;
isActive = true;
}
function cancel() public {
require(isActive, "contract must be active");
require(owner == msg.sender, "Only the owner can cancel the bounty");
uint256 bountyTemp = bounty;
bounty = 0;
owner.transfer(bountyTemp);
isActive = false;
emit Cancel(msg.sender, bountyTemp);
}
function setAndTransferToProvider(address addy) public {
require(isActive, "contract must be active");
require(owner == msg.sender, "Only the owner release the funds");
provider = payable(addy);
provider.transfer(bounty);
uint256 bountyUsed = bounty;
bounty = 0;
isActive = false;
emit Paid(owner, provider, bountyUsed);
}
function increaseBounty() payable external returns (uint256) {
require(isActive, "contract must be active");
require(owner == msg.sender, "Only the owner can increase the bounty");
uint oldBounty = bounty;
bounty += uint(msg.value);
emit IncreaseBounty(oldBounty, bounty);
return bounty;
}
function getBounty() public view returns (uint256) {
require(isActive, "contract must be active");
return bounty;
}
}

Try to put this line
provider.transfer(bounty);
right before the emit of the events on every function.
You can check this article for more understanding of reentrancy attacks.

Related

I'm trying to create a token store contract

When creating this contract, line "_buyer.transfer(buyers[_buyer]);" generates an error " "send" and "transfer" are only available for objects of type "address payable", not "address". ".
Here is the contract code.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract CoinStore {
address owner;
mapping(address => uint256) buyers;
mapping(address => uint256) sellers;
uint256 coinPrice;
bool tradePaused;
constructor() {
owner = msg.sender;
}
function setCoinPrice(uint256 _price) public {
require(msg.sender == owner, "Only the owner can set the coin price.");
coinPrice = _price;
}
function registerBuyer(address _buyer, uint256 _amount) public {
require(!tradePaused, "Trading is currently paused.");
buyers[_buyer] = _amount;
}
function registerSeller(address _seller, uint256 _amount) public {
require(!tradePaused, "Trading is currently paused.");
sellers[_seller] = _amount;
}
function pauseTrade() public {
require(msg.sender == owner, "Only the owner can pause trading.");
tradePaused = true;
}
function startTrade() public {
require(msg.sender == owner, "Only the owner can start trading.");
tradePaused = false;
}
function completeSale(address _buyer, address _seller) public payable {
require(_buyer.balance >= buyers[_buyer], "Buyer does not have enough funds.");
require(_seller.balance >= sellers[_seller], "Seller does not have enough funds.");
require(msg.value == coinPrice, "Incorrect payment amount.");
_buyer.transfer(buyers[_buyer]);
_seller.transfer(sellers[_seller]);
if (msg.value > buyers[_buyer]) {
_buyer.transfer(msg.value - buyers[_buyer]);
}
}
function withdrawFunds() public {
require(msg.sender == owner, "Only the owner can withdraw funds.");
msg.sender.transfer(address(this).balance);
}
}
I am a recent learner of Solidity and am not an expert in smart contract development. Everything I could I tried. Help me please. Thank you.
The address that you are trying to send to has to be payable aswell.
Your withdraw should look like this:
function withdrawFunds() public {
require(msg.sender == owner, "Only the owner can withdraw funds.");
payable(msg.sender).transfer(address(this).balance);
}

Getting Block Hash of another contract

I've seen some problems with calling functions from other contracts but I believe my problem is fairly genuine to demand a separate question if only to be negated in its possibility.
So I am trying to call a contract within another contract. Is it possible to get the blockhash of a particular block number of the callee contract within my caller? If so how?
Every syntax I've attempted fails for some reason.
Contract A
enter code here
contract DiceGame {
uint256 public nonce = 0;
uint256 public prize = 0;
event Roll(address indexed player, uint256 roll);
event Winner(address winner, uint256 amount);
constructor() payable {
resetPrize();
}
function resetPrize() private {
prize = ((address(this).balance * 10) / 100);
}
function rollTheDice() public payable {
require(msg.value >= 0.002 ether, "Failed to send enough value");
bytes32 prevHash = blockhash(block.number - 1);
bytes32 hash = keccak256(abi.encodePacked(prevHash, address(this), nonce));
uint256 roll = uint256(hash) % 16;
console.log('\t'," Dice Game Roll:",roll);
nonce++;
prize += ((msg.value * 40) / 100);
emit Roll(msg.sender, roll);
if (roll > 2 ) {
return;
}
uint256 amount = prize;
(bool sent, ) = msg.sender.call{value: amount}("");
require(sent, "Failed to send Ether");
resetPrize();
emit Winner(msg.sender, amount);
}
receive() external payable { }
}
Contract B
enter code here
contract RiggedRoll is Ownable {
DiceGame public diceGame;
constructor(address payable diceGameAddress) {
diceGame = DiceGame(diceGameAddress);
}
//Add withdraw function to transfer ether from the rigged contract to an address
//Add riggedRoll() function to predict the randomness in the DiceGame contract and only roll when it's going to be a winner
function riggedRoll(bytes32 riggedHash) public payable {
riggedHash = address(diceGame).blockhash(block.number-1); //I am aware this syntax is broken but I am not able to find a legitimate one to access the data from contract A.
}
//Add receive() function so contract can receive Eth
receive() external payable { }
}
A contract doesn't know when it was last called, unless you explicitly store this information.
Then you can get the block hash using the native blockhash() function (accepts the block number as a parameter).
contract Target {
uint256 public lastCalledAtBlockNumber;
// The value is stored only if you invoke the function using a (read-write) transaction.
// If you invoke the function using a (read-only) call, then it's not stored.
function foo() external {
lastCalledAtBlockNumber = block.number;
}
}
bytes32 blockHash = blockhash(block.number);

Problem sending eth from contract to contract

pragma solidity ^0.8.7;
// SPDX-License-Identifier: MIT
contract Client {
address payable private hub;
address payable public owner;
uint256 public balance;
constructor(address payable _hub) {
hub = _hub;
owner = payable(msg.sender);
}
receive() payable external {
balance += msg.value;
}
function withdraw(address payable destAddr) public {
require(msg.sender == owner, "Only owner can withdraw funds");
uint amount = address(this).balance;
destAddr.transfer(amount);
}
function start() public payable {
require(msg.sender == owner, "Only owner can start the process");
uint amount = address(this).balance;
hub.transfer(amount);
balance = 0;
}
function setHub(address payable _new) public {
require(msg.sender == owner, "Only owner can change address");
hub = _new;
}
}
Hi i have a problem, when I deploy this contract and put as input (hub) the other contract, then send eth to this contract, i call the "start" function and throw a gas estimation error.
Someone who can help me pls...
I'm expecting that calling the start function fund will be sent to the other contract that also have a function for receiving eth
receive() payable external {
balance += msg.value;
}
You are getting that gas estimation error because your receive function on the second contract is not empty and the transaction does not have enough gas to execute the code. transfer only sends the amount of gas necessary to execute a transfer of ether (21,000 gas) and nothing more.
You can use call instead of transfer to send ether and set the amount of gas that you want to send. transfer is actually no longer recommended for sending ether.

Solidity: transfer function uses which from address, contract address or caller's address?

contract MarketplaceEscrow {
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner {
require(owner == msg.sender, "Only the owner of the marketplace can perform this action");
_;
}
modifier onlyArbiter {
require(arbiter == msg.sender, "Only the designated marker can perform this action");
_;
}
function setProductDeliveredAndReleaseFunds(uint _productId) public onlyArbiter {
Product memory product = products[_productId];
productPurchaseHistoryForBuyer[buyer][_productId].status = eStatus.product_delivered;
Seller memory seller = product.seller;
uint priceether = product.priceEther;
uint price = priceether*10**18;
payable(seller.sellerAddress).transfer(price);
}
I tested the above function from the truffle console like this:
mp = await MarketplaceEscrow.deployed();
mp.setProductDeliveredAndReleaseFunds(24, {from: arbiter_address});
But I get an error. My question is whether the arbiter's address is being used by the code for sending funds to seller, or whether the contract address is being used. Thank you for the help.

Openzeppelin ERC20 make revert

my intent is making ERC721 token can transfer by my ERC20 token only
the transfer flow is
Buyer approve ERC20 to Seller.
Seller transfer ERC721 to Buyer.
My ERC721 Token's transfer function transfer ERC20 to Seller from Buyer first, and transfer ERC721 to Buyer from Seller.
revert error occur to ERC20 transfer step.
i try to every single line delete to find revert point.
and i found that.
this is my test code
const token20 = artifacts.require("MyToken20");
const token721 = artifacts.require("MyToken721");
contract("Test", async()=>{
//...
// Buyer token20 approve to Seller
it("Token20 approve", async()=>{
var value = web3.toWei(token721Price, "ether");
await contract20.approve(seller, value, {from:buyer});
var allowed = await contract20.allowance(buyer, seller);
allowed = web3.fromWei(allowed, "ether");
assert.equal(allowed, token721Price);
});
// Seller transfer token721 to Buyer
// token20 transfer to Seller inside of function transferMy721
it("Token721 transfer", async()=>{
var allowed = await contract20.allowance(buyer, seller);
allowed = web3.fromWei(allowed, "ether");
assert.equal(allowed, token721Price);
await contract721.transferMy721(buyer, token721Id, {from:seller}); // <--- revert here
var newOwner = await contract721.ownerOf(token721Id);
assert.equal(newOwner, buyer);
});
});
and revert point in my contract is here
contract MyToken721 is ERC721Token{
string public name = "My ERC721 Token Product";
string public symbol = "MTP";
mapping(uint256 => uint256) my721TokenPrice;
MyToken20 token;
constructor(MyToken20 _token) public ERC721Token(name, symbol){
require(_token != address(0));
token = _token;
}
function mint(address _to, uint256 _tokenId, uint256 _price) public {
_mint(_to, _tokenId);
my721TokenPrice[_tokenId] = _price;
}
function transferMy721(address _to, uint256 _tokenId) public returns(bool){
require(msg.sender == ownerOf(_tokenId));
uint256 tokenPrice = my721TokenPrice[_tokenId];
if( token.transferFrom(_to, msg.sender, tokenPrice) == false ) // <--- revert here
return false;
super.approve(_to, _tokenId);
super.transferFrom(msg.sender, _to, _tokenId);
return true;
}
//...
}
and revert point in ERC20 StandardToken contract is here
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;
function transferFrom(address _from, address _to, uint256 _value)
public returns (bool)
{
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]); // <--- revert here
require(_to != address(0));
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
emit Transfer(_from, _to, _value);
return true;
}
//...
}
as you can see, in my test code, i double check
allowed[_from][msg.sender]
please check my full code here
the one calling transferFrom is my erc721 contract.
so, i change test code
await contract20.approve(seller, value, {from:buyer});
change to
await contract20.approve(contract721.address, value, {from:buyer});
thank you for SylTi