This is Auction smart contract.
I want to make Auction like this. If someone registers his product for biding, anyone who want to buy can join on this bidding.
But When I test on Remix, it can't be complied even.
I think my coding is problem.
Please help me.
pragma solidity ^0.5.0;
contract Auction{
//product for auction
struct Product{
string name;
string description;
uint time;
}
//top bid
uint topMoney;
//presen owner of product
mapping (uint => address) productToOwner;
//owner of top bidder
mapping (uint => address) topMoneyOwner;
event Listed(uint id, string name, uint itme);
Product[] public products;
//register product
function listUp(string memory _name, string memory _description) public {
//time limit for bidding, 1 minutes;
uint time = now + 1 minutes;
//index of product
uint id = products.push(Product(_name, _description, time)) - 1;
//initial bid = 0
topMoney=0;
//initial owner of product
productToOwner[id] = msg.sender;
emit Listed(id, _name, time);
}
//bidding
function bidOn() payable public {
if ( topMoney < msg.value){
topMoney = msg.value;
topMoneyOwner[topMoney] = msg.sender;
} else {
msg.sender.transfer(msg.value);
}
}
//bidding end? return (bool)
function _end(uint _id) private view returns (bool) {
require(now >= products[_id].time);
return true;
}
//who is winner? Then, transfer money to owner of product.
function winner(uint _id) public {
require( true == _end(_id));
address(uint160(productToOwner[_id])).transfer(topMoney);
productToOwner[_id] = topMoneyOwner[topMoney];
}
}
Related
I created a basic contract for crowdfunding. But cannot figure out how to create a withdraw function.
Withdraw function will transfer a campaign's collected funds to the campaign's owner. This is my full crowdfunding contract:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
contract CrowdFunding {
event testConditon(
uint256 deadline,
uint256 currentTimeInMs,
uint256 diff,
bool condition
);
struct Campaign {
address payable owner;
string title;
string description;
uint256 target;
uint256 deadline;
uint256 amountCollected;
string image;
address[] donators;
uint256[] donations;
}
mapping(uint256 => Campaign) public campaigns;
uint256 public numberOfCampaigns = 0;
function createCampaign(
address _owner,
string memory _title,
string memory _description,
uint256 _target,
uint256 _deadline,
string memory _image
) public returns (uint256) {
Campaign storage campaign = campaigns[numberOfCampaigns];
uint256 currentTimeInMs = block.timestamp * 1000;
emit testConditon(
_deadline,
currentTimeInMs,
_deadline - currentTimeInMs,
_deadline > currentTimeInMs
);
require(
_deadline > currentTimeInMs,
"The deadline must be in the future"
);
campaign.owner = payable(_owner);
campaign.title = _title;
campaign.description = _description;
campaign.target = _target;
campaign.deadline = _deadline;
campaign.image = _image;
campaign.amountCollected = 0;
numberOfCampaigns++;
return numberOfCampaigns - 1;
}
function donateToCampaign(uint256 _id) public payable {
uint256 amount = msg.value;
Campaign storage campaign = campaigns[_id];
campaign.donators.push(msg.sender);
campaign.donations.push(amount);
(bool sent, ) = payable(campaign.owner).call{value: amount}("");
if (sent) {
campaign.amountCollected += amount;
}
}
function getDonators(uint256 _id)
public
view
returns (address[] memory, uint256[] memory)
{
return (campaigns[_id].donators, campaigns[_id].donations);
}
function getCampaigns() public view returns (Campaign[] memory) {
Campaign[] memory allCampaigns = new Campaign[](numberOfCampaigns);
for (uint256 i = 0; i < numberOfCampaigns; i++) {
Campaign storage item = campaigns[i];
allCampaigns[i] = item;
}
return allCampaigns;
}
function withdraw(uint256 _id) public {
Campaign storage campaign = campaigns[_id];
require(
campaign.amountCollected >= campaign.target,
"The campaign has not reached its target"
);
//deadline has passed
// require(
// campaign.deadline < block.timestamp * 1000,
// "The deadline has not passed yet"
// );
require(
campaign.owner == msg.sender,
"Only the owner of the campaign can withdraw the funds"
);
campaign.owner.transfer(campaign.amountCollected);
campaign.amountCollected = 0;
}
}
I have no idea how to solve this issue.
Looks like you are missing the payable keyword to trigger the token transfer. Try this:
function withdraw(uint256 _id) public {
Campaign storage campaign = campaigns[_id];
(bool success, ) = payable(campaign.owner).call{value: campaign.amountCollected}("");
require(success, "Withdrawal failure");
campaign.amountCollected = 0;
}
Warning: this function and your function are having a reentrency vulnerability.
I am coding a coin flip contract. I have an issue with the amount sent by the smart contract to a player who wins the game.
What I want to do is: when you loose the coin flip, you loose your bet and when you win, you get 2 x the bet amount - our royalty. Yet, when I deploy the contract on Remix and test the PayWinner() function, I do not get 2x what I bet - royalty.
Thanks for your help!
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
contract CoinFlip {
uint roundId;
uint betAmount;
uint royalty;
address owner;
address payable[] players;
struct round {
address payable player;
uint betAmount;
bool playerChoice; // 0 = heads; 1 = tails
bool draw;
bool win;
uint winAmount;
}
round public myRound;
mapping (uint => round) public flipHistory; // map the roundId with the round data
constructor() {
owner = msg.sender;
betAmount = 0;
roundId = 0;
}
function setRoyalty(uint _royalty) public onlyOwner returns (uint) {
return royalty = _royalty / 100;
}
function getRandomNumber(uint _bet, bool _playerChoice) public payable {
// minimum amount to be bet
require(msg.value > .001 ether);
// update the array players with the latest player
players.push(payable(msg.sender));
// update roundId
roundId = roundId+1;
// update player in Struct
myRound.player = payable(msg.sender);
// update betAmount in Struct
myRound.betAmount = _bet;
// update playerChoice in Struct
myRound.playerChoice = _playerChoice;
myRound.draw = uint256(keccak256(abi.encodePacked(
msg.sender,
)
)
)
% 2 == 1;
payWinner();
}
function payWinner() private {
if (myRound.draw == myRound.playerChoice) { // if else statement
myRound.win = true;
// compute amount to be transferred to winner
myRound.winAmount = myRound.betAmount * (2 - royalty);
// update mapping
flipHistory[roundId] = myRound;
payable(myRound.player).transfer(myRound.winAmount);
}
else {
myRound.win = false;
// update mapping
flipHistory[roundId] = myRound;
}
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
}
The error I am getting when I compile is: (ParserError: Expected primary expression.price = _price; * (1 ether);)
I would like to add a timestamp of 7 days for the promoter to add all funds to escrow in full not half to meet my conditions to book us. Is this even possible as a condition for us on our in? Do I need a multisig added to my smart contract to make it secure on both sides or is this code ok? Can anyone assist me in solving this problem?
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
contract Escrow {
//VARIBALES
enum State { NOT_INITIATED, AWAITING_PAYMENT, AWAITING_DELIVERY, COMPLETE }
State public currState;
bool public isBuyerIn;
bool public isSellerIn;
uint public price;
address public buyer;
address payable public seller;
//MODIFIERS
modifier onlyBuyer() {
require(msg.sender == buyer, "Only buyer can call this function"); _;
}
modifier escrowNotStarted() {
require(currState == State.NOT_INITIATED);
_;
}
//FUCTIONS
constructor(address _buyer, address payable _seller, uint _price){
buyer =_buyer;
seller = _seller;
price = _price; * (1 ether);
}
function initContract() escrowNotStarted public{
if(msg.sender == buyer) {
isBuyerIn = true;
}
if (msg.sender == seller) {
isSellerIn = true;
}
if (isBuyerIn && isSellerIn) {
currState = State.AWAITING_PAYMENT;
}
}
function deposit() onlyBuyer public payable {
require(currState == State.AWAITING_PAYMENT, "Already paiid");
require(msg.value == price, "Wrong deposit amount");
currState = State.AWAITING_DELIVERY;
}
function confimDelivery() onlyBuyer payable public {
require(currState == State.AWAITING_DELIVERY, "Cannot confirm delivery");
seller.transfer(price);
currState = State.COMPLETE;
}
function withdraw() onlyBuyer payable public {
require(currState == State.AWAITING_DELIVERY, "Cannot withdraw at this stage");
payable(msg.sender).transfer(price);
currState = State.COMPLETE;
}
}
You have an extra semicolon on the price assigning line in the constructor.
Replace
// original code, extra semicolon
price = _price; * (1 ether);
with
// updated code, removed the semicolon
price = _price * (1 ether);
I am creating a nft collection and I want the random owner to receive a percentage of the mint price with each mint. But since I need to wait for the VRF response, can't figure out how to implement randomness function and function that will send the percentage to the vrf response (random owner).
pragma solidity >=0.7.0 <0.9.0;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract Sofb is ERC721Enumerable, Ownable, VRFConsumerBase {
using Strings for uint256;
string baseURI;
string public baseExtension = ".json";
uint256 public cost = 0.015 ether;
uint256 public maxSupply = 7070;
uint256 public tokenCounter;
bool public paused = false;
bool public revealed = false;
string public notRevealedUri;
bytes32 internal keyHash;
uint256 internal fee;
uint256 public randomResult = 0;
address payable giftAddress = payable(msg.sender);
uint256 giftValue = 0;
mapping(bytes32 => uint256) public requestIdToRandomNumber;
mapping(bytes32 => address) public requestIdToAddress;
mapping(bytes32 => uint256) public requestIdToRequestNumberIndex;
uint256 public requestCounter;
constructor(string memory _name, string memory _symbol, string memory _initBaseURI, string memory _initNotRevealedUri, address _vrfCoordinator, address _linkToken, bytes32 _keyHash, uint256 _fee)
VRFConsumerBase(_vrfCoordinator, _linkToken)
ERC721(_name, _symbol) {
setBaseURI(_initBaseURI);
setNotRevealedURI(_initNotRevealedUri);
keyHash = _keyHash;
fee = _fee;
}
// internal
function _baseURI() internal view virtual override returns (string memory) {
return baseURI;
}
// public
function getRandomNumber() public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
requestIdToAddress[requestId] = msg.sender;
requestIdToRequestNumberIndex[requestId] = requestCounter;
requestCounter += 1;
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
requestIdToRandomNumber[requestId] = randomness;
uint256 requestNumber = requestIdToRequestNumberIndex[requestId];
}
function mint() public payable {
uint256 supply = totalSupply();
require(!paused);
require(supply + 1 <= maxSupply);
require(msg.value >= cost);
if (msg.sender != owner()) {
require(msg.value >= cost);
}
if (supply > 0) {
require(randomResult > 0);
giftAddress = payable(ownerOf(randomResult));
giftValue = ((supply + 1 == 5) || (supply + 1 == 10)) ? address(this).balance * 1 / 100 : msg.value * 10 / 100;
(bool success, ) = payable(giftAddress).call{value: giftValue}("");
require(success);
}
_safeMint(msg.sender, supply + 1);
getRandomNumber();
}
...
}
you should mint the token and put the mint logic inside the fulfillRandomness function, to access the data you will need i will recommend you to have an array of structs with the data you need, remember that random returns a requestId, use the request id as an index to get the stored data and then mint it, it's on you if you want to delete the data after mint the nft
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.