Skip to content

Commit 38b9e24

Browse files
Add Talent Plus smart contracts
1 parent 5879539 commit 38b9e24

File tree

13,038 files changed

+1381
-1371805
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

13,038 files changed

+1381
-1371805
lines changed

contracts/passport/TalentPlus.sol

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.24;
3+
4+
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
5+
import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
6+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8+
import "./PassportBuilderScore.sol";
9+
import "./TalentPlusSubscription.sol";
10+
import "@openzeppelin/contracts/access/Ownable.sol";
11+
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
12+
13+
contract TalentPlus is Ownable, ReentrancyGuard {
14+
using ECDSA for bytes32;
15+
using SafeERC20 for IERC20;
16+
17+
// TALENT token address
18+
IERC20 public immutable TALENT_TOKEN;
19+
20+
address public trustedSigner;
21+
address public feeReceiver;
22+
PassportBuilderScore public passportBuilderScore;
23+
PassportRegistry public passportRegistry;
24+
TalentPlusSubscription public talentPlusSubscription;
25+
26+
event SubscriptionCreated(address indexed user, uint256 score, uint256 onchainId, string subscriptionSlug);
27+
28+
bool public enabled;
29+
30+
constructor(
31+
address _trustedSigner,
32+
address _passportBuilderScoreAddress,
33+
address _passportRegistryAddress,
34+
address _talentPlusSubscriptionAddress,
35+
address _feeReceiver,
36+
address _talentTokenAddress
37+
) Ownable(msg.sender) {
38+
trustedSigner = _trustedSigner;
39+
passportBuilderScore = PassportBuilderScore(_passportBuilderScoreAddress);
40+
passportRegistry = PassportRegistry(_passportRegistryAddress);
41+
talentPlusSubscription = TalentPlusSubscription(_talentPlusSubscriptionAddress);
42+
feeReceiver = _feeReceiver;
43+
TALENT_TOKEN = IERC20(_talentTokenAddress);
44+
enabled = true;
45+
}
46+
47+
/**
48+
* @notice Enables or disables the TalentPlus contract.
49+
* @param _enabled Whether the TalentPlus contract should be enabled.
50+
* @dev Can only be called by the owner.
51+
*/
52+
function setEnabled(bool _enabled) public onlyOwner {
53+
enabled = _enabled;
54+
}
55+
56+
/**
57+
* @notice Disables the TalentPlus contract.
58+
* @dev Can only be called by the owner.
59+
*/
60+
function setDisabled() public onlyOwner {
61+
enabled = false;
62+
}
63+
64+
/**
65+
* @notice Updates the TalentPlusSubscription contract address.
66+
* @param _talentPlusSubscriptionAddress The new TalentPlusSubscription contract address.
67+
* @dev Can only be called by the owner.
68+
*/
69+
function updateTalentPlusSubscription(address _talentPlusSubscriptionAddress) public onlyOwner {
70+
require(_talentPlusSubscriptionAddress != address(0), "Invalid TalentPlusSubscription address");
71+
talentPlusSubscription = TalentPlusSubscription(_talentPlusSubscriptionAddress);
72+
}
73+
74+
/**
75+
* @notice Updates the fee receiver address.
76+
* @param _feeReceiver The new fee receiver address.
77+
* @dev Can only be called by the owner.
78+
*/
79+
function updateReceiver(address _feeReceiver) public onlyOwner {
80+
feeReceiver = _feeReceiver;
81+
}
82+
83+
/**
84+
* @notice Creates a subscription if the provided number is signed by the trusted signer.
85+
* @param score The number to be attested.
86+
* @param onchainId The onchain ID to receive the subscription.
87+
* @param subscriptionSlug The subscription slug to set in TalentPlusSubscription.
88+
* @param signature The signature of the trusted signer.
89+
*/
90+
function subscribe(uint256 score, uint256 onchainId, string memory subscriptionSlug, bytes memory signature) public nonReentrant {
91+
require(enabled, "Subscription is disabled for this contract");
92+
require(bytes(subscriptionSlug).length > 0, "Subscription slug cannot be empty");
93+
94+
// Get the subscription model details including price
95+
(, uint256 subscriptionCost, bool isActive) = talentPlusSubscription.getSubscriptionModel(subscriptionSlug);
96+
require(isActive, "Subscription model is not active");
97+
98+
// Hash the number
99+
bytes32 numberHash = keccak256(abi.encodePacked(score, onchainId));
100+
101+
// Recover the address that signed the hash
102+
address signer = MessageHashUtils.toEthSignedMessageHash(numberHash).recover(signature);
103+
104+
// Ensure the signer is the trusted signer
105+
require(signer == trustedSigner, "Invalid signature");
106+
107+
// Transfer TALENT tokens from user to fee receiver
108+
TALENT_TOKEN.safeTransferFrom(msg.sender, feeReceiver, subscriptionCost);
109+
110+
// Set the user subscription in TalentPlusSubscription
111+
talentPlusSubscription.addUserSubscription(onchainId, subscriptionSlug);
112+
113+
// Set the score in PassportBuilderScore
114+
require(passportBuilderScore.setScore(onchainId, score), "Failed to set score");
115+
116+
emit SubscriptionCreated(msg.sender, score, onchainId, subscriptionSlug);
117+
}
118+
}

0 commit comments

Comments
 (0)