Skip to content

Commit 3d23f0d

Browse files
authored
optimizations: reduce gas usage (#13)
* opt: reduce deployment costs by using constant instead of immutable * refactor: fix typo in registrable * refactor: remove comments since we are restricting to EOA and receivable contracts * opt: avoid unnecessary owner check in renew * opt: avoid checking for balance != 0 before returning funds * opt: remove check for recoveryAddress != custodyAdress * update gas snapshot
1 parent fba38a4 commit 3d23f0d

File tree

3 files changed

+96
-120
lines changed

3 files changed

+96
-120
lines changed

.gas-snapshot

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,53 +19,52 @@ AccountRegistryTest:testRegister() (gas: 89924)
1919
AccountRegistryTest:testRequestRecovery() (gas: 144852)
2020
AccountRegistryTest:testSetRecoveryAddress() (gas: 95427)
2121
AccountRegistryTest:testTransfer() (gas: 75750)
22-
NameSpaceTest:testBidAfterOneStep() (gas: 217674)
23-
NameSpaceTest:testBidAndOverpay() (gas: 213205)
24-
NameSpaceTest:testBidFlatRate() (gas: 216052)
25-
NameSpaceTest:testBidImmediately() (gas: 229367)
26-
NameSpaceTest:testBidOnHundredthStep() (gas: 216052)
27-
NameSpaceTest:testBidOnPenultimateStep() (gas: 216042)
28-
NameSpaceTest:testBidShouldClearRecovery() (gas: 260030)
29-
NameSpaceTest:testCancelRecoveryFromCustodyAddress() (gas: 221424)
30-
NameSpaceTest:testCancelRecoveryFromRecoveryAddress() (gas: 221008)
31-
NameSpaceTest:testCannotBidIfRegisterable() (gas: 30973)
32-
NameSpaceTest:testCannotBidUnlessBiddable() (gas: 173326)
33-
NameSpaceTest:testCannotCancelRecoveryIfNotStarted() (gas: 185626)
34-
NameSpaceTest:testCannotCancelRecoveryIfUnauthorized() (gas: 232195)
35-
NameSpaceTest:testCannotCommitWithInvalidName() (gas: 22838)
36-
NameSpaceTest:testCannotCompleteRecoveryIfExpired() (gas: 244224)
37-
NameSpaceTest:testCannotCompleteRecoveryIfNotStarted() (gas: 189905)
38-
NameSpaceTest:testCannotCompleteRecoveryIfUnauthorized() (gas: 217487)
39-
NameSpaceTest:testCannotCompleteRecoveryWhenInEscrow() (gas: 233829)
22+
NameSpaceTest:testBidAfterOneStep() (gas: 217603)
23+
NameSpaceTest:testBidAndOverpay() (gas: 213134)
24+
NameSpaceTest:testBidFlatRate() (gas: 215981)
25+
NameSpaceTest:testBidImmediately() (gas: 229318)
26+
NameSpaceTest:testBidOnHundredthStep() (gas: 215959)
27+
NameSpaceTest:testBidOnPenultimateStep() (gas: 215971)
28+
NameSpaceTest:testBidShouldClearRecovery() (gas: 259941)
29+
NameSpaceTest:testCancelRecoveryFromCustodyAddress() (gas: 221316)
30+
NameSpaceTest:testCancelRecoveryFromRecoveryAddress() (gas: 220922)
31+
NameSpaceTest:testCannotBidIfRegistrable() (gas: 30961)
32+
NameSpaceTest:testCannotBidUnlessBiddable() (gas: 173313)
33+
NameSpaceTest:testCannotCancelRecoveryIfNotStarted() (gas: 185540)
34+
NameSpaceTest:testCannotCancelRecoveryIfUnauthorized() (gas: 232109)
35+
NameSpaceTest:testCannotCommitWithInvalidName() (gas: 22905)
36+
NameSpaceTest:testCannotCompleteRecoveryIfExpired() (gas: 244138)
37+
NameSpaceTest:testCannotCompleteRecoveryIfNotStarted() (gas: 189819)
38+
NameSpaceTest:testCannotCompleteRecoveryIfUnauthorized() (gas: 217405)
39+
NameSpaceTest:testCannotCompleteRecoveryWhenInEscrow() (gas: 233743)
4040
NameSpaceTest:testCannotReclaimUnlessMinted() (gas: 17407)
4141
NameSpaceTest:testCannotRegisterWithoutPayment() (gas: 85851)
42-
NameSpaceTest:testCannotRenewIfBiddable() (gas: 163382)
43-
NameSpaceTest:testCannotRenewIfOwnerIncorrect() (gas: 165376)
44-
NameSpaceTest:testCannotRenewIfRegisterable() (gas: 32191)
45-
NameSpaceTest:testCannotRenewIfRegistered() (gas: 163466)
46-
NameSpaceTest:testCannotRenewWithoutPayment() (gas: 156300)
47-
NameSpaceTest:testCannotRequestRecoveryIfRegisterable() (gas: 26437)
48-
NameSpaceTest:testCannotRequestRecoveryToZeroAddr() (gas: 185464)
49-
NameSpaceTest:testCannotRequestRecoveryUnlessAuthorized() (gas: 163876)
50-
NameSpaceTest:testCannotSetRecoveryIfExpired() (gas: 165042)
51-
NameSpaceTest:testCannotSetRecoveryIfRegisterable() (gas: 20854)
52-
NameSpaceTest:testCannotSetRecoveryUnlessOwner() (gas: 158705)
53-
NameSpaceTest:testCannotSetSelfAsRecovery() (gas: 154747)
54-
NameSpaceTest:testCurrYear() (gas: 78269)
42+
NameSpaceTest:testCannotRenewIfBiddable() (gas: 162869)
43+
NameSpaceTest:testCannotRenewIfRegistered() (gas: 162953)
44+
NameSpaceTest:testCannotRenewIfRegistrable() (gas: 31908)
45+
NameSpaceTest:testCannotRenewIfRegistrable2() (gas: 31950)
46+
NameSpaceTest:testCannotRenewWithoutPayment() (gas: 156012)
47+
NameSpaceTest:testCannotRequestRecoveryIfRegistrable() (gas: 26459)
48+
NameSpaceTest:testCannotRequestRecoveryToZeroAddr() (gas: 185400)
49+
NameSpaceTest:testCannotRequestRecoveryUnlessAuthorized() (gas: 163808)
50+
NameSpaceTest:testCannotSetRecoveryIfExpired() (gas: 164996)
51+
NameSpaceTest:testCannotSetRecoveryIfRegistrable() (gas: 20896)
52+
NameSpaceTest:testCannotSetRecoveryUnlessOwner() (gas: 158592)
53+
NameSpaceTest:testCurrYear() (gas: 78247)
5554
NameSpaceTest:testCurrYearPayment() (gas: 45881)
56-
NameSpaceTest:testGenerateCommit() (gas: 40372)
57-
NameSpaceTest:testOwnerOfRevertsIfExpired() (gas: 152817)
58-
NameSpaceTest:testOwnerOfRevertsIfRegisterable() (gas: 12847)
59-
NameSpaceTest:testReclaimBiddableNames() (gas: 181574)
60-
NameSpaceTest:testReclaimRegisteredNames() (gas: 190244)
61-
NameSpaceTest:testReclaimRenewableNames() (gas: 181517)
62-
NameSpaceTest:testReclaimResetsRecoveryState() (gas: 226138)
63-
NameSpaceTest:testRecoveryCompletion() (gas: 245203)
64-
NameSpaceTest:testRegister() (gas: 255657)
65-
NameSpaceTest:testRenewOther() (gas: 175546)
66-
NameSpaceTest:testRenewSelf() (gas: 172971)
67-
NameSpaceTest:testRenewWithOverpayment() (gas: 178190)
68-
NameSpaceTest:testRequestRecovery() (gas: 241657)
69-
NameSpaceTest:testSetRecoveryAddress() (gas: 189815)
70-
NameSpaceTest:testTransferFromCannotTransferExpiredName() (gas: 171509)
71-
NameSpaceTest:testTransferFromResetsRecovery() (gas: 225498)
55+
NameSpaceTest:testGenerateCommit() (gas: 40350)
56+
NameSpaceTest:testOwnerOfRevertsIfExpired() (gas: 152771)
57+
NameSpaceTest:testOwnerOfRevertsIfRegistrable() (gas: 12872)
58+
NameSpaceTest:testReclaimBiddableNames() (gas: 181528)
59+
NameSpaceTest:testReclaimRegisteredNames() (gas: 190207)
60+
NameSpaceTest:testReclaimRenewableNames() (gas: 181560)
61+
NameSpaceTest:testReclaimResetsRecoveryState() (gas: 226069)
62+
NameSpaceTest:testRecoveryCompletion() (gas: 245134)
63+
NameSpaceTest:testRegister() (gas: 255587)
64+
NameSpaceTest:testRenewOther() (gas: 174360)
65+
NameSpaceTest:testRenewSelf() (gas: 171777)
66+
NameSpaceTest:testRenewWithOverpayment() (gas: 177327)
67+
NameSpaceTest:testRequestRecovery() (gas: 241593)
68+
NameSpaceTest:testSetRecoveryAddress() (gas: 189689)
69+
NameSpaceTest:testTransferFromCannotTransferExpiredName() (gas: 171463)
70+
NameSpaceTest:testTransferFromResetsRecovery() (gas: 225429)

src/Namespace.sol

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ error InvalidTime(); // Time is too far in the future or past
1616
error IncorrectOwner(); // The username is not owned by the expected address
1717

1818
error Registered(); // The username is currently registered.
19-
error NotRegisterable(); // The username has been registered and cannot be registered again.
20-
error Registerable(); // The username has never been registered.
19+
error NotRegistrable(); // The username has been registered and cannot be registered again.
20+
error Registrable(); // The username has never been registered.
2121

2222
error Expired(); // The username is expired (renewable or biddable)
2323
error Biddable(); // The username is biddable
@@ -38,7 +38,7 @@ contract Namespace is ERC721, Owned {
3838
REGISTRATION EVENTS
3939
//////////////////////////////////////////////////////////////*/
4040

41-
event Renew(uint256 indexed tokenId, address indexed to, uint256 expiry);
41+
event Renew(uint256 indexed tokenId, uint256 expiry);
4242

4343
/*//////////////////////////////////////////////////////////////
4444
RECOVERY EVENTS
@@ -81,11 +81,11 @@ contract Namespace is ERC721, Owned {
8181
/*//////////////////////////////////////////////////////////////
8282
CONSTANTS
8383
//////////////////////////////////////////////////////////////*/
84-
string public baseURI = "http://www.farcaster.xyz/";
84+
string public constant baseURI = "http://www.farcaster.xyz/";
8585

86-
uint256 public immutable gracePeriod = 30 days;
86+
uint256 public constant gracePeriod = 30 days;
8787

88-
uint256 public immutable fee = 0.01 ether;
88+
uint256 public constant fee = 0.01 ether;
8989

9090
// The epoch timestamp of Jan 1 for each year starting from 2022
9191
uint256[] internal _yearTimestamps = [
@@ -110,7 +110,7 @@ contract Namespace is ERC721, Owned {
110110

111111
address public immutable vault;
112112

113-
uint256 immutable escrowPeriod = 3 days;
113+
uint256 constant escrowPeriod = 3 days;
114114

115115
constructor(
116116
string memory _name,
@@ -186,7 +186,7 @@ contract Namespace is ERC721, Owned {
186186
delete stateOf[commit];
187187

188188
uint256 tokenId = uint256(bytes32(username));
189-
if (expiryOf[tokenId] != 0) revert NotRegisterable();
189+
if (expiryOf[tokenId] != 0) revert NotRegistrable();
190190

191191
_mint(owner, tokenId);
192192

@@ -195,26 +195,21 @@ contract Namespace is ERC721, Owned {
195195
expiryOf[tokenId] = timestampOfYear(currYear() + 1);
196196
}
197197

198-
// TODO: this may fail if called by a smart contract
199-
if (msg.value > _currYearFee) {
200-
payable(msg.sender).transfer(msg.value - _currYearFee);
201-
}
198+
payable(msg.sender).transfer(msg.value - _currYearFee);
202199
}
203200

204201
/**
205202
* @notice Renew a name for another year while it is in the renewable period
206203
*
207204
* @param tokenId the tokenId of the name to renew
208-
* @param owner the current owner of the name
209205
*/
210-
function renew(uint256 tokenId, address owner) external payable {
206+
function renew(uint256 tokenId) external payable {
211207
if (msg.value < fee) revert InsufficientFunds();
212208

213209
uint256 expiryTs = expiryOf[tokenId];
214-
if (expiryTs == 0) revert Registerable();
210+
if (expiryTs == 0) revert Registrable();
215211

216212
// Invariant 1B + 2 guarantee that the name is not owned by address(0) at this point.
217-
if (_ownerOf[tokenId] != owner) revert IncorrectOwner();
218213

219214
unchecked {
220215
// renewTs and gracePeriod are pre-determined values and cannot overflow
@@ -226,12 +221,9 @@ contract Namespace is ERC721, Owned {
226221
expiryOf[tokenId] = timestampOfYear(currYear() + 1);
227222
}
228223

229-
emit Renew(tokenId, owner, expiryOf[tokenId]);
224+
emit Renew(tokenId, expiryOf[tokenId]);
230225

231-
// TODO: this may fail if called by a smart contract
232-
if (msg.value > fee) {
233-
payable(msg.sender).transfer(msg.value - fee);
234-
}
226+
payable(msg.sender).transfer(msg.value - fee);
235227
}
236228

237229
/**
@@ -246,7 +238,7 @@ contract Namespace is ERC721, Owned {
246238
*/
247239
function bid(uint256 tokenId) external payable {
248240
uint256 expiryTs = expiryOf[tokenId];
249-
if (expiryTs == 0) revert Registerable();
241+
if (expiryTs == 0) revert Registrable();
250242

251243
uint256 auctionStartTimestamp;
252244

@@ -278,10 +270,7 @@ contract Namespace is ERC721, Owned {
278270
expiryOf[tokenId] = timestampOfYear(currYear() + 1);
279271
}
280272

281-
// TODO: this may revert if called by a smart contract
282-
if (msg.value > price) {
283-
payable(msg.sender).transfer(msg.value - price);
284-
}
273+
payable(msg.sender).transfer(msg.value - price);
285274
}
286275

287276
/*//////////////////////////////////////////////////////////////
@@ -295,7 +284,7 @@ contract Namespace is ERC721, Owned {
295284
uint256 expiryTs = expiryOf[tokenId];
296285

297286
// Invariant 1A will ensure a throw if a name was not minted, as per the ERC-721 spec.
298-
if (expiryTs == 0) revert Registerable();
287+
if (expiryTs == 0) revert Registrable();
299288

300289
if (block.timestamp >= expiryTs) revert Expired();
301290

@@ -321,7 +310,7 @@ contract Namespace is ERC721, Owned {
321310
_clearRecovery(id);
322311
}
323312

324-
function tokenURI(uint256 tokenId) public view override returns (string memory) {
313+
function tokenURI(uint256 tokenId) public pure override returns (string memory) {
325314
return string(abi.encodePacked(baseURI, tokenId, ".json"));
326315
}
327316

@@ -350,8 +339,6 @@ contract Namespace is ERC721, Owned {
350339
function setRecoveryAddress(uint256 tokenId, address recoveryAddress) external payable {
351340
if (ownerOf(tokenId) != msg.sender) revert Unauthorized();
352341

353-
if (recoveryAddress == msg.sender) revert InvalidRecovery();
354-
355342
recoveryOf[tokenId] = recoveryAddress;
356343
emit SetRecoveryAddress(recoveryAddress, tokenId);
357344
}
@@ -436,7 +423,7 @@ contract Namespace is ERC721, Owned {
436423
* @param tokenId the uint256 representation of the username.
437424
*/
438425
function reclaim(uint256 tokenId) external payable onlyOwner {
439-
if (expiryOf[tokenId] == 0) revert Registerable();
426+
if (expiryOf[tokenId] == 0) revert Registrable();
440427

441428
unchecked {
442429
// this value is deterministic and cannot overflow for any known year

0 commit comments

Comments
 (0)