Reputation: 65
I have a Rinkeby Metamask account that I would like to get students to pay me 10 Ether, to show that they have understood the following principles as part of a challenge:
Once this payment has gone through I would like to give them a text string say "Well_Done_101" that would prove they have completed the challenge.
I understand that smart contracts are available but I'm not sure how this would work as I would want the text string to be invisible until the payment has been completed.
This is some code that I tried earlier:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract payment_for_art {
// default value is `false`, don't need to explicitly state it
bool isPaid;
function winner() public view returns (string memory) {
return flag;
}
function hidden() private view returns (string memory) {
string memory flag_true;
flag_true = 'Well_done_101';
return flag;
}
function invest() external payable {
// to prevent multiple payments
// reverts if the condition is not met
require(isPaid == false);
if(msg.value < 10 ether) {
revert('Pay me the full amount');
}
if(isPaid = true) { // flag that the payment has been done
//return ('Well_Done_101');
return flag_true;
}
}
function balance_of() external view returns(uint) {
return address(this).balance;
}
}
Any ideas or comments would be greatly appreciated.
Upvotes: 0
Views: 201
Reputation: 1336
I think what you're searching for is something like this.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract payment_for_art {
// Mappings of studentNames to flag; Its like a key => value list data type.
// Public storage variables can be accessed by anyone (solidity creates a getter implicitly), but can't be modified directly.
mapping (string => string) public buyers;
// Recieves the payment, and also the students name (your students must call this function with their name as a parameter).
function invest(string memory studentName) external payable {
// check if "studentname" isn't empty.
require(bytes(studentName).length != 0, "You forgot to specify your student name.");
// check if the payment is 10 eth.
require(msg.value == 10 ether, "You are either paying too much, or too little.");
// check if the student already bought, by checking if his flag is set in the mapping.
require(bytes(buyers[studentName]).length == 0, "You already bought the art.");
// set flag for student.
// While regular string literals can only contain ASCII,
// Unicode literals – prefixed with the keyword unicode – can contain any valid UTF-8 sequence (this allows you to use emogis and whatnot).
// They also support the very same escape sequences as regular string literals.
buyers[studentName] = unicode"Well_Done_101 😃";
}
function balance_of() external view returns(uint) {
return address(this).balance;
}
}
And to check if they bought, just call the mapping and search for your students name.
Example made using web3:
payment_for_artContract.methods.invest("Daniel Jackson")
.send({ from: account, value: weiValue})
.on('transactionHash', (hash) => {
const studentsWhoBought = await payment_for_artContract.methods.buyers().call();
// prints "Well_Done_101 😃";
console.log(studentsWhoBought["Daniel Jackson"]);
console.log(studentsWhoBought);
})
.on('error', (err) => {
console.error(err);
})
If you want to actually get a value from it when its called, you'll need to use events (triggers that clients can subscribe to) and have web3 subscribe to said event.
For example:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract payment_for_art {
// Mappings of studentNames to flag; Its like a key => value list data type.
// Public storage variables can be accessed by anyone (solidity creates a getter implicitly), but can't be modified directly.
mapping (string => string) public buyers;
// Event of buying.
event Bought(string studentName, address studentAddress, string flag);
// Recieves the payment, and also the students name (your students must call this function with their name as a parameter).
function invest(string memory studentName) external payable {
// check if "studentname" isn't empty.
require(bytes(studentName).length != 0, "You forgot to specify your student name.");
// check if the payment is 10 eth.
require(msg.value == 10 ether, "You are either paying too much, or too little.");
// check if the student already bought, by checking if his flag is set in the mapping.
require(bytes(buyers[studentName]).length == 0, "You already bought the art.");
// set flag for student.
// While regular string literals can only contain ASCII,
// Unicode literals – prefixed with the keyword unicode – can contain any valid UTF-8 sequence (this allows you to use emogis and whatnot).
// They also support the very same escape sequences as regular string literals.
buyers[studentName] = unicode"Well_Done_101 😃";
emit Bought(studentName, msg.sender, unicode"Well_Done_101 😃");
}
function balance_of() external view returns(uint) {
return address(this).balance;
}
}
And then in web3:
payment_for_artContract.methods.invest("Daniel Jackson")
.send({ from: account, value: weiValue})
.on('transactionHash', (hash) => {
console.log("transaction mined");
})
.on('error', (err) => {
console.error(err);
});
const options = {
fromBlock: 0, // Number || "earliest" || "pending" || "latest"
toBlock: 'latest'
};
payment_for_artContract.events.Bought(options)
// prints the student's name who bought, address of the student, and "Well_Done_101 😃";
.on('data', event => console.log(event))
.on('changed', changed => console.log(changed))
.on('error', err => throw err)
.on('connected', str => console.log(str));
I would stick with the first method, since its easier, yet the second method is how it should be properly done.
Try that, and let me know if thats what you were searching for :)
Upvotes: 1