university.alchemy9

Your Goal: Members 你的目标:成员

Create a public constructor which takes an array of address. These addresses, plus the deployer of the function, should all be allowed to create new proposals and vote on those proposals.
创建一个公共的constructor,该函数接受一个address数组作为参数。这些地址以及该函数的部署者都应被允许创建新提案并对这些提案进行投票。
If anyone else attempts to create a proposal or vote, the call should be reverted.
如果有其他人试图创建提案或进行投票,调用应被回滚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Voting {
struct Proposal {
address target;
bytes data;
uint yesCount;
uint noCount;
}

Proposal[] public proposals;

// Mapping to track members who can create proposals and vote
mapping(address => bool) public members;

// Constructor to initialize the contract with allowed members
constructor(address[] memory _members) {
// Add the deployer as a member
members[msg.sender] = true;

// Add all addresses from the input array as members
for (uint i = 0; i < _members.length; i++) {
members[_members[i]] = true;
}
}

// Modifier to ensure only members can create proposals and vote
modifier onlyMember() {
require(members[msg.sender], "Not authorized to perform this action");
_;
}

event ProposalCreated(uint proposalId);
event VoteCast(uint proposalId, address voter);
// Mapping to track if an address has voted on a particular proposal
mapping(uint => mapping(address => bool)) public hasVoted;

// Mapping to store the vote (true = yes, false = no) of each address for each proposal
mapping(uint => mapping(address => bool)) public votes;

// Function to create a new proposal
function newProposal(address addr, bytes calldata data) onlyMember external {
Proposal memory newProposalInstance = Proposal(addr, data, 0, 0);
proposals.push(newProposalInstance);
emit ProposalCreated(proposals.length - 1); // proposalId is the index of the newly added proposal
//每当创建新的Proposal结构体时,就触发该事件。
}

// Function to cast or change a vote
function castVote(uint proposalId, bool support) onlyMember external {
// Ensure the proposal exists
require(proposalId < proposals.length, "Proposal does not exist");

// Retrieve the proposal to update its vote counts
Proposal storage targetProposal = proposals[proposalId];

// If the voter has already voted, we need to change their vote
if (hasVoted[proposalId][msg.sender]) {
emit VoteCast(proposalId, msg.sender);
// If the voter previously voted "yes" and now votes "no"
if (votes[proposalId][msg.sender] == true && !support) {
targetProposal.yesCount -= 1; // Decrease yesCount
targetProposal.noCount += 1; // Increase noCount
}
// If the voter previously voted "no" and now votes "yes"
else if (votes[proposalId][msg.sender] == false && support) {
targetProposal.noCount -= 1; // Decrease noCount
targetProposal.yesCount += 1; // Increase yesCount
}
} else {
emit VoteCast(proposalId, msg.sender);
// If the voter has not voted yet, just increase the respective count
if (support) {
targetProposal.yesCount += 1;
} else {
targetProposal.noCount += 1;
}
}

// Update the voter's choice
votes[proposalId][msg.sender] = support;

// Mark that this address has voted for this proposal
hasVoted[proposalId][msg.sender] = true;
}
}

Your Goal: Execute 你的目标:执行

Let’s make our minimum voting threshold be 10 participants. Once 10 members have voted yes on a proposal, execute it.
让我们将最低投票门槛设为10名参与者。一旦有10名成员对某项提案投了赞成票,就执行该提案。

Update the castVote function to execute the proposal when the 10 yes votes have been registered.
更新castVote函数,以便在登记到10张赞成票时执行该提案。
Execute the vote by sending the data to the target address using the call syntax.
使用call语法将data发送到target地址来执行投票。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Voting {
struct Proposal {
address target;
bytes data;
uint yesCount;
uint noCount;
}

Proposal[] public proposals;

// Constructor to initialize the contract with allowed members
constructor(address[] memory _members) {
// Add the deployer as a member
members[msg.sender] = true;

// Add all addresses from the input array as members
for (uint i = 0; i < _members.length; i++) {
members[_members[i]] = true;
}
}

// Modifier to ensure only members can create proposals and vote
modifier onlyMember() {
require(members[msg.sender], "Not authorized to perform this action");
_;
}
event ProposalExecuted(uint proposalId);
event ProposalCreated(uint proposalId);
event VoteCast(uint proposalId, address voter);
// Mapping to track if an address has voted on a particular proposal
mapping(uint => mapping(address => bool)) public hasVoted;

// Mapping to store the vote (true = yes, false = no) of each address for each proposal
mapping(uint => mapping(address => bool)) public votes;

mapping(uint => uint) public supportingVotes;

// Mapping to track members who can create proposals and vote
mapping(address => bool) public members;

// Function to create a new proposal
function newProposal(address addr, bytes calldata data) onlyMember external {
Proposal memory newProposalInstance = Proposal(addr, data, 0, 0);
proposals.push(newProposalInstance);
emit ProposalCreated(proposals.length - 1); // proposalId is the index of the newly added proposal
//每当创建新的Proposal结构体时,就触发该事件。
}

// Function to cast or change a vote
function castVote(uint proposalId, bool support) onlyMember external {
//number10 = 0
//这个变量从0开始,一旦有10名成员对某项提案投了赞成票,就执行该提案。
// Ensure the proposal exists
require(proposalId < proposals.length, "Proposal does not exist");

// Retrieve the proposal to update its vote counts
Proposal storage targetProposal = proposals[proposalId];

// If the voter has already voted, we need to change their vote
if (hasVoted[proposalId][msg.sender]) {
emit VoteCast(proposalId, msg.sender);
// If the voter previously voted "yes" and now votes "no"
if (votes[proposalId][msg.sender] == true && !support) {
targetProposal.yesCount -= 1; // Decrease yesCount
targetProposal.noCount += 1; // Increase noCount
supportingVotes[proposalId] -= 1; // Decrease supporting votes
//number10 += 1;
//如果投票了,此变量就加一
}
// If the voter previously voted "no" and now votes "yes"
else if (votes[proposalId][msg.sender] == false && support) {
targetProposal.noCount -= 1; // Decrease noCount
targetProposal.yesCount += 1; // Increase yesCount
supportingVotes[proposalId] += 1; // Increase supporting votes
//number10 += 1;
//如果投票了,此变量就加一
}
} else {
emit VoteCast(proposalId, msg.sender);
// If the voter has not voted yet, just increase the respective count
if (support) {
targetProposal.yesCount += 1;
supportingVotes[proposalId] += 1; // Increase supporting votes
} else {
targetProposal.noCount += 1;
}
}

// Update the voter's choice
votes[proposalId][msg.sender] = support;

// Mark that this address has voted for this proposal
hasVoted[proposalId][msg.sender] = true;

// Check if the proposal has enough supporting votes to be executed
if (supportingVotes[proposalId] >= 10) {
executeProposal(proposalId);
}
emit VoteCast(proposalId, msg.sender);

}
// Function to execute a proposal once it has enough supporting votes
function executeProposal(uint proposalId) internal {
// Ensure the proposal exists
require(proposalId < proposals.length, "Proposal does not exist");

Proposal storage targetProposal = proposals[proposalId];

// Execute the proposal by calling the target address with the proposal's data
(bool success, ) = targetProposal.target.call(targetProposal.data);

// If the call is successful, emit the execution event
require(success, "Proposal execution failed");

emit ProposalExecuted(proposalId);
}
}

继承

child合约可以继承所有的函数和状态变量,除了private

使用override关键字,可以覆盖一些方法

现在它有一个constructor,该函数接受一个health参数。请问constructor是放在contract外面还是{里面}

在 Solidity 中,constructor(构造函数)必须放在 contract { } 内部,它是合约的 “初始化方法”,属于合约的核心成员,不能定义在合约外部(外部定义会直接编译报错)。

Your Goal: Specific Health 你的目标:特定生命值

You’ll notice that the Hero.sol file has changed on this stage! Now it has a constructor which takes a health argument.
你会注意到本阶段的Hero.sol文件发生了变化!现在它有一个constructor,该函数接受一个health参数。

Let’s modify our SuperHeroes so that Warrior has an initial health of 200 while the Mage has an initial health of 50.
让我们修改我们的超级英雄,使Warrior的初始生命值为200,而Mage的初始生命值为50。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "./Hero.sol";


// TODO: create Mage/Warrior Heroes
contract Mage is Hero(50) {
//uint Mage = 50;

}

contract Warrior is Hero(200) {
//uint Warrior = 200;
}

这是上层合约

1
2
3
4
5
6
7
8
9
10
11
12
13
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

contract Hero {
uint public health;
constructor(uint _health) {
health = _health;
}

function takeDamage(uint damage) public {
health -= damage;
}
}

Your Goal: SuperHero Attacks 你的目标:超级英雄攻击

You’ll notice the Hero.sol tab has changed once again! This time there’s three important things to notice:
你会注意到Hero.sol标签又一次发生了变化!这次有三件重要的事情需要注意:

The Hero contract is an abstract contract. It has a virtual function called attack which we’ll need to override in both Warrior and Mage.
Hero合约是一个抽象合约。它有一个名为attack的virtual函数,我们需要在战士和法师中都重写这个函数。
An enum called AttackTypes has been added to the Hero contract to differentiate between the different types of attacks our heroes can do.
Hero合约中添加了一个名为AttackTypes的enum,用于区分我们的英雄可以执行的不同攻击类型。
There’s a contract called Enemy which has a method called takeAttack on it.
有一个名为Enemy的合约,它上面有一个名为takeAttack的方法。
Your job is to implement the attack function on the Warrior and Mage contracts:
你的任务是在Warrior(战士)和Mage(法师)合约上实现attack(攻击)函数:

Add an override function called attack to both the Warrior and Mage contracts. This function should take an Enemy parameter which will be an Enemy contract.
向Warrior和Mage合约中添加一个名为attack的override函数。该函数应接受一个Enemy参数,该参数将是一个Enemy合约。
Invoke takeAttack function on the Enemy contract and change the parameter based on the hero:
调用Enemy合约上的takeAttack函数,并根据英雄修改参数:
For the Warrior, invoke the enemy’s takeAttack with the Brawl attack type.
对于战士,使用Brawl攻击类型调用敌人的takeAttack。
For the Mage, invoke the enemy’s takeAttack with the Spell attack type.
对于法师,使用“法术”攻击类型调用敌人的takeAttack。