问题描述
我有一个 Rinkeby Metamask 账户,我想让学生支付我 10 以太币,以表明他们已经理解以下原则作为挑战的一部分:
- 创建一个处理以太坊的在线钱包
- 能够获得足够的免费以太坊来完成支付
- 最后一次支付全款
付款完成后,我想给他们一个文本字符串“Well_Done_101”,以证明他们已完成挑战。
我知道可以使用智能合约,但我不确定这将如何工作,因为我希望文本字符串在付款完成之前不可见。
这是我之前尝试过的一些代码:
// 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;
}
}
任何想法或意见将不胜感激。
解决方法
我认为您要搜索的内容是这样的。
// 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;
}
}
要检查他们是否购买,只需调用映射并搜索您的学生姓名即可。
使用 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);
})
如果您想在它被调用时实际从中获取一个值,您需要使用事件(客户端可以订阅的触发器)并让 web3 订阅所述事件。
例如:
// 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,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;
}
}
然后在 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));
我会坚持第一种方法,因为它更容易,但第二种方法应该如何正确完成。
尝试一下,如果这就是您要搜索的内容,请告诉我:)