Skip to content

Commit fc53953

Browse files
committed
Hook up ERC20 token and payout fnction
1 parent b747c34 commit fc53953

File tree

11 files changed

+428
-112
lines changed

11 files changed

+428
-112
lines changed

contracts/GoldenProtocol.sol

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,35 @@
22
pragma solidity ^0.8.16;
33

44
import '@openzeppelin/contracts/access/Ownable.sol';
5-
5+
import './GoldenToken.sol';
66
import './libraries/AddressSet.sol';
77

88
/// @custom:security-contact security@golden.com
99
contract GoldenProtocol is Ownable {
10-
using AddressSet for AddressSet.Set;
11-
// This is not going to scale well... how to keep track of questions without this?
12-
AddressSet.Set _questions;
10+
GoldenToken tokenContract;
11+
uint256 public minimumBounty;
1312
uint256 public minimumVotes;
1413

15-
constructor(uint256 _minimumVotes) Ownable() {
14+
event QuestionCreated(
15+
address indexed questionAddress,
16+
bytes16 subjectUUID,
17+
bytes16 predicateUUID
18+
);
19+
20+
constructor(
21+
address goldenTokenAddress,
22+
uint256 _minimumBounty,
23+
uint256 _minimumVotes
24+
) Ownable() {
25+
tokenContract = GoldenToken(goldenTokenAddress);
26+
minimumBounty = _minimumBounty;
1627
minimumVotes = _minimumVotes;
1728
}
1829

30+
function setMinimumBounty(uint256 _minimumBounty) external onlyOwner {
31+
minimumBounty = _minimumBounty;
32+
}
33+
1934
function setMinimumVotes(uint256 _minimumVotes) public onlyOwner {
2035
minimumVotes = _minimumVotes;
2136
}
@@ -25,30 +40,33 @@ contract GoldenProtocol is Ownable {
2540
bytes16 predicateUUID,
2641
uint256 bounty
2742
) public returns (address) {
43+
require(bounty >= minimumBounty, 'GoldenProtocol: bounty is too low');
44+
require(
45+
tokenContract.allowance(_msgSender(), address(this)) >= bounty,
46+
'GoldenProtocol: insufficient allowance'
47+
);
48+
2849
// TODO: Creating new contracts is going to be very expensive.
2950
// Is there a cheaper alternative to encapsulate the question logic?
3051
GoldenProtocolQuestion newQuestion = new GoldenProtocolQuestion(
52+
address(tokenContract),
3153
msg.sender,
3254
subjectUUID,
33-
predicateUUID,
34-
bounty
55+
predicateUUID
3556
);
3657
address newQuestionAddress = address(newQuestion);
37-
_questions.insert(newQuestionAddress);
58+
tokenContract.transferFrom(_msgSender(), newQuestionAddress, bounty);
59+
emit QuestionCreated(newQuestionAddress, subjectUUID, predicateUUID);
3860
return newQuestionAddress;
3961
}
40-
41-
// TODO: This is not going to scale well... how to keep track of questions without this?
42-
function questions() public view returns (address[] memory) {
43-
return _questions.keyList;
44-
}
4562
}
4663

4764
contract GoldenProtocolQuestion is Ownable {
65+
GoldenToken tokenContract;
66+
4867
using AddressSet for AddressSet.Set;
4968

5069
address public asker;
51-
uint256 public bounty;
5270
bytes16 public subjectUUID;
5371
bytes16 public predicateUUID;
5472
string public answer;
@@ -72,28 +90,38 @@ contract GoldenProtocolQuestion is Ownable {
7290
uint256 voteCount;
7391
}
7492

93+
event AnswerAdded(
94+
bytes16 subjectUUID,
95+
bytes16 predicateUUID,
96+
string answer,
97+
uint256 index
98+
);
99+
75100
constructor(
101+
address goldenTokenAddress,
76102
address _asker,
77103
bytes16 _subjectUUID,
78-
bytes16 _predicateUUID,
79-
uint256 _bounty
104+
bytes16 _predicateUUID
80105
) Ownable() {
81106
require(
82107
_asker != address(0),
83108
'GoldenProtocolQuestion: asker is the zero address'
84109
);
85-
110+
tokenContract = GoldenToken(goldenTokenAddress);
86111
asker = _asker;
87112
subjectUUID = _subjectUUID;
88113
predicateUUID = _predicateUUID;
89-
bounty = _bounty;
90114
}
91115

92116
modifier onlyAsker() {
93117
require(msg.sender == asker, 'GoldenProtocolQuestion: onlyAsker');
94118
_;
95119
}
96120

121+
function bounty() public view returns (uint256) {
122+
return tokenContract.balanceOf(address(this));
123+
}
124+
97125
function addAnswer(string calldata _answer) public {
98126
require(
99127
bytes(_answer).length > 0,
@@ -104,6 +132,12 @@ contract GoldenProtocolQuestion is Ownable {
104132
answerByAnswerer[answerer] = _answer;
105133
answerers.upsert(answerer);
106134
voteCountByAnswerer[answerer] = 0;
135+
emit AnswerAdded(
136+
subjectUUID,
137+
predicateUUID,
138+
_answer,
139+
answerers.indexOfKey(answerer)
140+
);
107141
}
108142

109143
function answers() public view returns (Answer[] memory) {
@@ -159,7 +193,10 @@ contract GoldenProtocolQuestion is Ownable {
159193
);
160194
answer = _topAnswer.answer;
161195
address payable answerer = payable(_topAnswer.answerer);
162-
answerer.transfer(bounty);
196+
tokenContract.transfer(
197+
answerer,
198+
tokenContract.balanceOf(address(this))
199+
);
163200
}
164201

165202
// Utils

contracts/GoldenToken.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ contract GoldenToken is
2828
) internal override {
2929
super._beforeTokenTransfer(from, to, amount);
3030

31-
require(
32-
(from == address(0) ||
33-
from == owner() ||
34-
from == address(this) ||
35-
to == address(this)),
36-
'ERC20: Not allowed to transfer'
37-
);
31+
// require(
32+
// (from == address(0) ||
33+
// from == owner() ||
34+
// from == address(this) ||
35+
// to == address(this)),
36+
// 'ERC20: Not allowed to transfer'
37+
// );
3838
}
3939

4040
// ============ Staking ============

contracts/libraries/AddressSet.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,12 @@ library AddressSet {
5858
{
5959
return self.keyList[index];
6060
}
61+
62+
function indexOfKey(Set storage self, address key)
63+
internal
64+
view
65+
returns (uint256)
66+
{
67+
return self.keyPointers[key];
68+
}
6169
}

deploy/0_GoldenProtocol.ts renamed to deploy/999_GoldenProtocol.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@ const deploy: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
66

77
const { deployer } = await getNamedAccounts();
88

9+
const GoldenTokenDeployment = await deployments.get('GoldenToken');
10+
911
await deployments.deploy('GoldenProtocol', {
1012
from: deployer,
1113
// skipIfAlreadyDeployed: true,
12-
args: [3],
14+
args: [GoldenTokenDeployment.address, 3, 10],
1315
log: true,
1416
});
1517
};
1618

1719
deploy.id = 'deploy_golden_protocol';
1820
deploy.tags = ['GoldenProtocol'];
21+
deploy.dependencies = ['GoldenToken'];
1922

2023
export default deploy;

0 commit comments

Comments
 (0)