Struct within another struct Solidity - solidity

I just started learning solidity and I am working on a bidding contract that allows bidders to bid on a campaign.
I have a struct for campaigns. Bidders have details (address, name), I want to store bidders with their information inside of the campaign. There can be more than one bidder for a campaign
This is my Campaign and Bidder struct
struct Campaign {
uint256 campaignID;
uint256 budget;
uint256 bidCount;
}
struct Bidder {
bool bided;
uint256 bid;
string name;
address bidderAddress;
}
mapping(address => Bidder) public bidders;
Campaign[] public campaigns;
I wrote down a bid function here that takes the index of campaign and bid then populate bidCount.
function bid(uint256 _bidIndex, uint256 _twitterID) public {
require(!bidders[msg.sender].bided);
bidders[msg.sender].bid = _bidIndex;
campaigns[_bidIndex].bidCount += 1;
totalBids += 1;
}
So the Campaign can look something like this (if this is possible)
0: campaignID 1
1: budget 2ETH
2: bidCount 3
3: Bidder {0: name Bidder1, 1: address 0xahaaahha}
{0: name Bidder2, 2: address 0x2334jddd}
Any help will be greatly appreciated. Thanks

According to me, in this case you can use nested mapping into Campaign struct for 'connect' different bids to a single campaign. I created a smart contract ad hoc for your case, you can see it in the following lines:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract Auction {
address owner;
constructor() {
owner = msg.sender;
}
struct Campaign {
uint256 campaignID;
uint256 budget;
uint256 bidCount;
mapping(uint => Bidder[]) bidders;
}
struct Bidder {
bool bided;
uint256 bid;
string name;
address bidderAddress;
}
Campaign[] public campaigns;
uint totalCampaign = 0;
modifier onlyOwner {
require(msg.sender == owner, "Error! You're not the smart contract owner!");
_;
}
// Create campaigns
function createCampaing(uint _budgetCampaign) public onlyOwner {
Campaign storage _firstCampaigns = campaigns.push();
_firstCampaigns.campaignID = totalCampaign;
_firstCampaigns.budget = _budgetCampaign;
totalCampaign++;
}
// Bid
function bid(uint _indexCampaign, string memory _nameBidder) public {
Campaign storage _bidCampaign = campaigns[_indexCampaign];
_bidCampaign.bidCount += 1;
uint _bidIndex = _bidCampaign.bidCount;
_bidCampaign.bidders[_indexCampaign].push(Bidder(true, _bidIndex, _nameBidder, msg.sender));
}
// Getter Bids
function getBids(uint _indexCampaign) onlyOwner external view returns(Bidder[] memory) {
return campaigns[_indexCampaign].bidders[_indexCampaign];
}
}
With getBids() function, you retrieve all bids for a specific campaign that it identify with its index. I put a onlyOwner modifier that it allows to specific function that they'll call only from the smart contract owner (rather who deployed for first time smart contract into blockchain).

Related

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);

What is missing from this Smart Contract?

I am working on a smart contract, and my goal is that when a certain (variable) amount of eth gets send to the contract, it gets split and payed to three adresses. I currently have this code. Am I missing something? It doesn't work in Remix unfortunately. Thanks in advance for your valuable time!
`pragma solidity ^0.6.0;
contract PaymentSplitter {
address payable addressOne;
address payable addressTwo;
address payable addressThree;
uint256 amount;
constructor(address payable _addressOne = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2, address payable _addressTwo = 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db, address payable _addressThree = 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB) public {
addressOne = _addressOne;
addressTwo = _addressTwo;
addressThree = _addressThree;
}
function splitPayment(uint256 _amount) public {
amount = _amount;
addressOne.transfer(_amount / 3);
addressTwo.transfer(_amount / 3);
addressThree.transfer(_amount / 3);
}
function getSplitAmount() public view returns (uint256) {
return amount;
}
// This will be invoked when the contract receives a payment
function() external payable {
splitPayment(msg.value);
}
}`
We tried various smart contract, but without any significant results
I modified your smart contract. I put some notes, to understand you some errors in your logic:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract PaymentSplitter {
address payable addressOne;
address payable addressTwo;
address payable addressThree;
uint256 amount;
constructor(address _addressOne, address _addressTwo, address _addressThree) public {
addressOne = payable(_addressOne);
addressTwo = payable(_addressTwo);
addressThree = payable(_addressThree);
}
// NOTE: Avoid passing parameter with value because with this statement 'address(this).balance' I receive the entire amount of Ether stored in smart contract
function splitPayment() public {
// NOTE: I retrieve entire amount stored in smart contract balance after send value to it
uint smartContractBalance = address(this).balance;
// NOTE: Since smart contract balance should be divided into three equal part the amount, I make this operation one time and put the value inside 'amount' variable. Then
// I transfer the equal amount to three accounts.
amount = smartContractBalance / 3;
addressOne.transfer(amount);
addressTwo.transfer(amount);
addressThree.transfer(amount);
}
function getSplitAmount() public view returns (uint256) {
return amount;
}
// This will be invoked when the contract receives a payment
receive() external payable {
splitPayment();
}
}
NOTE: Consider to use address.call{value}() for send amount from smart contract to accounts.
Is this a better contract? A few changes, and different amounts have to be sent to different addresses.
pragma solidity ^0.8.17;
contract Blockbook{
address payable public address1;
address payable public address2;
address payable public address3;
constructor(address payable _address1, address payable _address2, address payable _address3) public {
address1 = _address1;
address2 = _address2;
address3 = _address3;
}
function splitPayment(uint amount) public payable {
address1.transfer(amount * 0.8);
address2.transfer(amount * 0.1);
address3.transfer(amount * 0.1);
}
receive() external payable {
splitPayment(msg.value);
}
function updateAddresses(address payable _address1, address payable _address2, address payable _address3) public {
address1 = _address1;
address2 = _address2;
address3 = _address3;
}
}

DeclarationError: Identifier not found or not unique

I'm trying to compile my sol file, but it's giving me this error. Why am I getting this error?
DeclarationError: Identifier not found or not unique. -->
project:/contracts/MemoTokenSale.sol:11:5: | 11 | MemoToken
public token; | ^^^^^^^^^
Compilation failed. See above. Truffle v5.4.23 (core: 5.4.23) Node
v16.13.0
The following is my code
// SPX-License-Identifier: MIT
pragma solidity ^0.8.0;
import './MemoToken.sol';
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract MemoTokenSale {
address payable public admin;
address payable private ethFunds = payable(0x15b22B37679eF92672dA117F4357e048319008AD); // Web3 Account
MemoToken public token;
uint256 public tokensSold;
int public tokenPriceUSD;
AggregatorV3Interface internal priceFeed;
uint256 public transactionCount;
event Sell(address _buyer, uint256 _amount);
struct Transaction {
address buyer;
uint256 amount;
}
mapping(uint256 => Transaction) public transaction;
constructor(MemoToken _token) {
priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331); // ChainLink Contracts
tokenPriceUSD = 50;
token = _token;
admin = payable(msg.sender);
}
function getETHPrice() public view returns(int) {
(, int price, , , ) = priceFeed.latestRoundData();
return (price / 10^8);
}
function memoTokenPriceInETH() public view returns(int) {
int ethPrice = getETHPrice();
return tokenPriceUSD / ethPrice;
}
function buyToken(uint256 _amount) public payable {
int memoTokenPriceETH = memoTokenPriceInETH();
// Check that the buyer sends the enough ETH
require(int(msg.value) >= memoTokenPriceETH * int(_amount));
// Check that the sale contract provides the enough ETH to make this transaction.
require(token.balanceOf(address(this)) >= _amount);
// Make the transaction inside of the require
// transfer returns a boolean value.
require(token.transfer(msg.sender, _amount));
// Transfer the ETH of the buyer to us
ethFunds.transfer(msg.value);
// Increase the amount of tokens sold
tokensSold += _amount;
// Increase the amount of transactions
transaction[transactionCount] = Transaction(msg.sender, _amount);
transactionCount++;
// Emit the Sell event
emit Sell(msg.sender, _amount);
}
function endSale() public {
require(msg.sender == admin);
// Return the tokens that were left inside of the sale contract
uint256 amount = token.balanceOf(address(this));
require(token.transfer(admin, amount));
selfdestruct(payable(admin));
}
}

payments ( pre set value) in solidity

i am developing a Movie renting smartcontract. Where the owner can add new movies, clients can search movies and pay for the movies they select.Adding and searching is working to my liking.
problem: i want to develop the pay function as such- where it takes one argument( the title of the movie) and clients has to pay the exact amount set by the owner, he can not pay less then the price.
for example: owner add a movie: title-titanic,price-10 eth. when client use the pay function he put the title titanic and pay 10 eth. if he tries to pay less or more the transaction will not be successful.
here is the code
pragma solidity 0.8.7;
// SPDX-License-Identifier: MIT
contract Movie{
address public owner;
struct Move{
uint year;
uint price;
}
mapping (string => Move ) public movieInfo;
mapping(uint => Move) amount;
constructor() payable{
owner= msg.sender;
}
function addMovie(string memory _title, uint _year, uint _price) public {
require( msg.sender==owner);
movieInfo[_title]= Move(_year, _price);
}
function pay(string memory _title) public payable{
}
function totalFunds() public view returns(uint){
return address(this).balance;
}
}
Don't think that this kind of stuff is good to store into the blockchain ATM, due to the highly cost of storing.
In case you would like to have it:
mapping(string -> address[]) paidUsers;
function pay(string memory _title) public payable {
require(msg.value == movieInfo[_title].price, "Invalid price for the film");
paidUsers[_title].push(msg.sender);
}

Math operation in a solidity contract

I want to create a function in solidity that receive an amount from person A, double the received amount using the contract account balance, then transfer the doubled amount to a person B. Up to now, I create the function which receive an external payable amount from only the person A, I note that the amount placed should be > 2 ether, but for doubling and transfer the amount, I'm little confused about the method.
contract MyContract {
address payable public personA;
address payable public personB;
mapping(address => uint) balances;
modifier onlyonlypersonA() {
require(msg.sender == onlypersonA, "Only onlypersonA can call this method");
_;}
function Send() onlypersonA external payable {
if(msg.value < 2 ether) {revert();}
balances[msg.sender] += msg.value;}
}
Try this:
contract MyContract {
address payable public personA;
address payable public personB;
mapping(address => uint) balances;
modifier onlyonlypersonA() {
require(msg.sender == onlypersonA, "Only onlypersonA can call this method");
_;}
function Send() onlypersonA external payable {
if(msg.value < 2 ether) {revert();}
balances[msg.sender] += msg.value;
// Try doubling
require(msg.value * 2 <= address(this).balance, "Insufficient funds to doubling");
personB.transfer(msg.value * 2);
}
}