This repository has been archived by the owner on Nov 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
FIFSAddrRegistrar.sol
146 lines (125 loc) · 5.11 KB
/
FIFSAddrRegistrar.sol
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
pragma solidity ^0.5.3;
import "@rsksmart/rns-registry/contracts/AbstractRNS.sol";
import "@rsksmart/rns-resolver/contracts/legacy/AbstractAddrResolver.sol";
import "./FIFSRegistrarBase.sol";
import "./PricedContract.sol";
/// @title First-in first-served registrar with automatic addr setup.
/// @notice You can use this contract to register names in RNS with addr
/// resolution set automatcially.
/// @dev This contract has permission to register in Node Owner.
contract FIFSAddrRegistrar is FIFSRegistrarBase, PricedContract {
address pool;
AbstractRNS rns;
bytes32 rootNode;
// sha3('register(string,address,bytes32,uint,address)')
bytes4 constant REGISTER_SIGNATURE = 0x5f7b99d5;
constructor (
ERC677 _rif,
NodeOwner _nodeOwner,
address _pool,
AbstractNamePrice _namePrice,
AbstractRNS _rns,
bytes32 _rootNode
) public FIFSRegistrarBase(_rif, _nodeOwner) PricedContract(_namePrice) {
pool = _pool;
rns = _rns;
rootNode = _rootNode;
}
/*
3. Execute registration via:
- ERC-20 with approve() + register()
- ERC-677 with transferAndCall()
The price of a domain is given by name price contract.
*/
// - Via ERC-20
/// @notice Registers a .rsk name in RNS.
/// @dev This method must be called after commiting.
/// @param name The name to register.
/// @param nameOwner The owner of the name to regiter.
/// @param secret The secret used to make the commitment.
/// @param duration Time to register in years.
/// @param addr Address to set as addr resolution.
function register(
string calldata name,
address nameOwner,
bytes32 secret,
uint duration,
address addr
) external {
uint cost = executeRegistration(name, nameOwner, secret, duration, addr);
require(rif.transferFrom(msg.sender, pool, cost), "Token transfer failed");
}
// - Via ERC-677
/* Encoding:
| signature | 4 bytes - offset 0
| owner | 20 bytes - offset 4
| secret | 32 bytes - offest 24
| duration | 32 bytes - offset 56
| duration | 20 bytes - offset 88
| name | variable size - offset 108
*/
/// @notice ERC-677 token fallback function.
/// @dev Follow 'Register encoding' to execute a one-transaction regitration.
/// @param from token sender.
/// @param value amount of tokens sent.
/// @param data data associated with transaction.
/// @return true if successfull.
function tokenFallback(address from, uint value, bytes calldata data) external returns (bool) {
require(msg.sender == address(rif), "Only RIF token");
require(data.length > 108, "Invalid data");
bytes4 signature = data.toBytes4(0);
require(signature == REGISTER_SIGNATURE, "Invalid signature");
address nameOwner = data.toAddress(4);
bytes32 secret = data.toBytes32(24);
uint duration = data.toUint(56);
address addr = data.toAddress(88);
string memory name = data.toString(108, data.length.sub(108));
registerWithToken(name, nameOwner, secret, duration, from, value, addr);
return true;
}
function registerWithToken(
string memory name,
address nameOwner,
bytes32 secret,
uint duration,
address from,
uint amount,
address addr
) private {
uint cost = executeRegistration(name, nameOwner, secret, duration, addr);
require(amount >= cost, "Not enough tokens");
require(rif.transfer(pool, cost), "Token transfer failed");
if (amount.sub(cost) > 0)
require(rif.transfer(from, amount.sub(cost)), "Token transfer failed");
}
/// @notice Executes registration abstracted from payment method.
/// @param name The name to register.
/// @param nameOwner The owner of the name to regiter.
/// @param secret The secret used to make the commitment.
/// @param duration Time to register in years.
/// @param addr Address to set as addr resolution.
/// @return price Price of the name to register.
function executeRegistration (
string memory name,
address nameOwner,
bytes32 secret,
uint duration,
address addr
) private returns (uint) {
bytes32 label = keccak256(abi.encodePacked(name));
uint256 tokenId = uint256(label);
require(name.strlen() >= minLength, "Short names not available");
bytes32 commitment = makeCommitment(label, nameOwner, secret);
require(canReveal(commitment), "No commitment found");
commitmentRevealTime[commitment] = 0;
nodeOwner.register(label, address(this), duration.mul(365 days));
AbstractAddrResolver(rns.resolver(rootNode))
.setAddr(
keccak256(abi.encodePacked(rootNode, label)),
addr
);
nodeOwner.reclaim(tokenId, nameOwner);
nodeOwner.transferFrom(address(this), nameOwner, tokenId);
return price(name, nodeOwner.expirationTime(uint(label)), duration);
}
}