Skip to content

Commit 26a77e0

Browse files
authored
change function selectors (#141)
Some services that inspect bytecode to determine the token type have falsely identified the base contract as an ERC721 due to the existence of certain function selectors in the fallback function. This change updates the function selectors for communication between the mirror contract and the base contract to avoid any overlap with ERC721 function selectors. It has been tested in a production environment and the services that were previously picking up the base ERC20 tokens as ERC721 no longer identify them as such.
1 parent 5eed081 commit 26a77e0

File tree

3 files changed

+22
-20
lines changed

3 files changed

+22
-20
lines changed

src/DN404.sol

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,8 +1200,8 @@ abstract contract DN404 {
12001200
);
12011201
_return(1);
12021202
}
1203-
// `setApprovalForAll(address,bool,address)`.
1204-
if (fnSelector == 0x813500fc) {
1203+
// `setApprovalForAllNFT(address,bool,address)`.
1204+
if (fnSelector == 0xf6916ddd) {
12051205
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
12061206
_setApprovalForAll(
12071207
address(uint160(_calldataload(0x04))), // `spender`.
@@ -1210,20 +1210,20 @@ abstract contract DN404 {
12101210
);
12111211
_return(1);
12121212
}
1213-
// `isApprovedForAll(address,address)`.
1214-
if (fnSelector == 0xe985e9c5) {
1213+
// `isApprovedForAllNFT(address,address)`.
1214+
if (fnSelector == 0x62fb246d) {
12151215
bool result = _isApprovedForAll(
12161216
address(uint160(_calldataload(0x04))), // `owner`.
12171217
address(uint160(_calldataload(0x24))) // `operator`.
12181218
);
12191219
_return(_toUint(result));
12201220
}
1221-
// `ownerOf(uint256)`.
1222-
if (fnSelector == 0x6352211e) {
1221+
// `ownerOfNFT(uint256)`.
1222+
if (fnSelector == 0x2d8a746e) {
12231223
_return(uint160(_ownerOf(_calldataload(0x04))));
12241224
}
1225-
// `ownerAt(uint256)`.
1226-
if (fnSelector == 0x24359879) {
1225+
// `ownerAtNFT(uint256)`.
1226+
if (fnSelector == 0xc016aa52) {
12271227
_return(uint160(_ownerAt(_calldataload(0x04))));
12281228
}
12291229
// `approveNFT(address,uint256,address)`.
@@ -1236,8 +1236,8 @@ abstract contract DN404 {
12361236
);
12371237
_return(uint160(owner));
12381238
}
1239-
// `getApproved(uint256)`.
1240-
if (fnSelector == 0x081812fc) {
1239+
// `getApprovedNFT(uint256)`.
1240+
if (fnSelector == 0x27ef5495) {
12411241
_return(uint160(_getApproved(_calldataload(0x04))));
12421242
}
12431243
// `balanceOfNFT(address)`.
@@ -1248,8 +1248,8 @@ abstract contract DN404 {
12481248
if (fnSelector == 0xe2c79281) {
12491249
_return(_totalNFTSupply());
12501250
}
1251-
// `tokenURI(uint256)`.
1252-
if (fnSelector == 0xc87b56dd) {
1251+
// `tokenURINFT(uint256)`.
1252+
if (fnSelector == 0xcb30b460) {
12531253
/// @solidity memory-safe-assembly
12541254
assembly {
12551255
mstore(0x40, add(mload(0x40), 0x20))

src/DN404Mirror.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ contract DN404Mirror {
125125
ownerOf(id); // `ownerOf` reverts if the token does not exist.
126126
// We'll leave if optional for `_tokenURI` to revert for non-existent token
127127
// on the ERC20 side, since this is only recommended by the ERC721 standard.
128-
return _readString(0xc87b56dd, id); // `tokenURI(uint256)`.
128+
return _readString(0xcb30b460, id); // `tokenURINFT(uint256)`.
129129
}
130130

131131
/// @dev Returns the total NFT supply from the base DN404 contract.
@@ -146,13 +146,13 @@ contract DN404Mirror {
146146
/// Requirements:
147147
/// - Token `id` must exist.
148148
function ownerOf(uint256 id) public view virtual returns (address) {
149-
return address(uint160(_readWord(0x6352211e, id, 0))); // `ownerOf(uint256)`.
149+
return address(uint160(_readWord(0x2d8a746e, id, 0))); // `ownerOfNFT(uint256)`.
150150
}
151151

152152
/// @dev Returns the owner of token `id` from the base DN404 contract.
153153
/// Returns `address(0)` instead of reverting if the token does not exist.
154154
function ownerAt(uint256 id) public view virtual returns (address) {
155-
return address(uint160(_readWord(0x24359879, id, 0))); // `ownerAt(uint256)`.
155+
return address(uint160(_readWord(0xc016aa52, id, 0))); // `ownerAtNFT(uint256)`.
156156
}
157157

158158
/// @dev Sets `spender` as the approved account to manage token `id` in
@@ -196,7 +196,7 @@ contract DN404Mirror {
196196
/// Requirements:
197197
/// - Token `id` must exist.
198198
function getApproved(uint256 id) public view virtual returns (address) {
199-
return address(uint160(_readWord(0x081812fc, id, 0))); // `getApproved(uint256)`.
199+
return address(uint160(_readWord(0x27ef5495, id, 0))); // `getApprovedNFT(uint256)`.
200200
}
201201

202202
/// @dev Sets whether `operator` is approved to manage the tokens of the caller in
@@ -209,7 +209,7 @@ contract DN404Mirror {
209209
assembly {
210210
operator := shr(96, shl(96, operator))
211211
let m := mload(0x40)
212-
mstore(0x00, 0x813500fc) // `setApprovalForAll(address,bool,address)`.
212+
mstore(0x00, 0xf6916ddd) // `setApprovalForAllNFT(address,bool,address)`.
213213
mstore(0x20, operator)
214214
mstore(0x40, iszero(iszero(approved)))
215215
mstore(0x60, caller())
@@ -238,8 +238,8 @@ contract DN404Mirror {
238238
virtual
239239
returns (bool)
240240
{
241-
// `isApprovedForAll(address,address)`.
242-
return _readWord(0xe985e9c5, uint160(nftOwner), uint160(operator)) != 0;
241+
// `isApprovedForAllNFT(address,address)`.
242+
return _readWord(0x62fb246d, uint160(nftOwner), uint160(operator)) != 0;
243243
}
244244

245245
/// @dev Transfers token `id` from `from` to `to`.

test/DN404.t.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ contract DN404Test is SoladyTest {
3838
}
3939

4040
function testTokenURI(string memory baseURI, uint256 id) public {
41+
id = _bound(id, 1, 1000);
4142
dn.initializeDN404(1000 * _WAD, address(this), address(mirror));
43+
dn.transfer(address(0xbeef), 1000 * _WAD);
4244
dn.setBaseURI(baseURI);
4345
string memory expected = string(abi.encodePacked(baseURI, id));
44-
assertEq(DN404Mirror(payable(address(dn))).tokenURI(id), expected);
46+
assertEq(DN404Mirror(payable(address(mirror))).tokenURI(id), expected);
4547
}
4648

4749
function testRegisterAndResolveAlias(address a0, address a1) public {

0 commit comments

Comments
 (0)