Skip to content

Commit

Permalink
Try fix via-ir
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Mar 19, 2024
1 parent 4a5272a commit 01e3f1e
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 112 deletions.
46 changes: 23 additions & 23 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ BenchTest:testMintDN420_13() (gas: 111640)
BenchTest:testMintDN420_14() (gas: 113114)
BenchTest:testMintDN420_15() (gas: 114496)
BenchTest:testMintDN420_16() (gas: 115948)
BenchTest:test__codesize() (gas: 28709)
BenchTest:test__codesize() (gas: 28697)
DN404CustomUnitTest:testInitializeCorrectUnitSuccess() (gas: 129992)
DN404CustomUnitTest:testInitializeWithUnitTooLargeReverts() (gas: 33824)
DN404CustomUnitTest:testInitializeWithZeroUnitReverts() (gas: 13897)
Expand Down Expand Up @@ -145,38 +145,38 @@ DN404Test:test__codesize() (gas: 57359)
DN420OnlyERC20Test:testApprove() (gas: 35770)
DN420OnlyERC20Test:testApprove(address,uint256) (runs: 258, μ: 30086, ~: 31321)
DN420OnlyERC20Test:testBurn() (gas: 50438)
DN420OnlyERC20Test:testBurn(address,uint256,uint256) (runs: 258, μ: 51572, ~: 51639)
DN420OnlyERC20Test:testBurnInsufficientBalanceReverts(address,uint256,uint256) (runs: 258, μ: 44649, ~: 44709)
DN420OnlyERC20Test:testBurn(address,uint256,uint256) (runs: 258, μ: 51558, ~: 51639)
DN420OnlyERC20Test:testBurnInsufficientBalanceReverts(address,uint256,uint256) (runs: 258, μ: 44641, ~: 44709)
DN420OnlyERC20Test:testInfiniteApproveTransferFrom() (gas: 102630)
DN420OnlyERC20Test:testMaxSupplyTrick(uint256) (runs: 258, μ: 541, ~: 541)
DN420OnlyERC20Test:testMetadata() (gas: 10112)
DN420OnlyERC20Test:testMint() (gas: 45958)
DN420OnlyERC20Test:testMintOverMaxLimitReverts() (gas: 41962)
DN420OnlyERC20Test:testMintz(address,uint256) (runs: 258, μ: 46269, ~: 46380)
DN420OnlyERC20Test:testMintz(address,uint256) (runs: 258, μ: 46257, ~: 46380)
DN420OnlyERC20Test:testTransfer() (gas: 75434)
DN420OnlyERC20Test:testTransfer(address,uint256) (runs: 258, μ: 75786, ~: 75891)
DN420OnlyERC20Test:testTransfer(address,uint256) (runs: 258, μ: 75765, ~: 75891)
DN420OnlyERC20Test:testTransferFrom() (gas: 85088)
DN420OnlyERC20Test:testTransferFrom(address,address,address,uint256,uint256) (runs: 258, μ: 105808, ~: 108058)
DN420OnlyERC20Test:testTransferFrom(address,address,address,uint256,uint256) (runs: 258, μ: 105791, ~: 108058)
DN420OnlyERC20Test:testTransferFromInsufficientAllowanceReverts() (gas: 68658)
DN420OnlyERC20Test:testTransferFromInsufficientAllowanceReverts(address,uint256,uint256) (runs: 258, μ: 69198, ~: 69823)
DN420OnlyERC20Test:testTransferFromInsufficientAllowanceReverts(address,uint256,uint256) (runs: 258, μ: 69188, ~: 69763)
DN420OnlyERC20Test:testTransferFromInsufficientBalanceReverts() (gas: 75577)
DN420OnlyERC20Test:testTransferFromInsufficientBalanceReverts(address,uint256,uint256) (runs: 258, μ: 76651, ~: 76698)
DN420OnlyERC20Test:testTransferFromInsufficientBalanceReverts(address,uint256,uint256) (runs: 258, μ: 76642, ~: 76698)
DN420OnlyERC20Test:testTransferInsufficientBalanceReverts() (gas: 67140)
DN420OnlyERC20Test:testTransferInsufficientBalanceReverts(address,uint256,uint256) (runs: 258, μ: 68269, ~: 68227)
DN420OnlyERC20Test:test__codesize() (gas: 26873)
DN420Test:testERC1155Methods(uint256) (runs: 258, μ: 4344623, ~: 4588648)
DN420Test:testERC1155MethodsSelfTransfers(uint256) (runs: 258, μ: 2500189, ~: 2683341)
DN420Test:testFindOwnedIds() (gas: 2647894)
DN420Test:testMintNext() (gas: 2124439)
DN420Test:testMintToNonERC155RecipientReverts(uint256) (runs: 258, μ: 935274, ~: 800745)
DN420Test:testMintToRevertingERC155RecipientReverts(uint256) (runs: 258, μ: 1421495, ~: 981677)
DN420Test:testMintToZeroReverts(uint256) (runs: 258, μ: 746923, ~: 664301)
DN420Test:testMixed(uint256) (runs: 258, μ: 10345519, ~: 6390023)
DN420Test:testSafeBatchTransferFromToERC1155Recipient(uint256) (runs: 258, μ: 2203130, ~: 2180647)
DN420Test:testSafeTransferFromToERC1155Recipient(uint256) (runs: 258, μ: 1770268, ~: 1474343)
DN420Test:testTransferFromToERC1155Recipient(uint256) (runs: 258, μ: 2879243, ~: 2866733)
DN420Test:testTransferMixedReverts(uint256) (runs: 258, μ: 3666699, ~: 2722022)
DN420Test:test__codesize() (gas: 66283)
DN420OnlyERC20Test:testTransferInsufficientBalanceReverts(address,uint256,uint256) (runs: 258, μ: 68178, ~: 68227)
DN420OnlyERC20Test:test__codesize() (gas: 26870)
DN420Test:testERC1155Methods(uint256) (runs: 258, μ: 4329154, ~: 4577238)
DN420Test:testERC1155MethodsSelfTransfers(uint256) (runs: 258, μ: 2462392, ~: 2068392)
DN420Test:testFindOwnedIds() (gas: 2646614)
DN420Test:testMintNext() (gas: 2123677)
DN420Test:testMintToNonERC155RecipientReverts(uint256) (runs: 258, μ: 904192, ~: 796788)
DN420Test:testMintToRevertingERC155RecipientReverts(uint256) (runs: 258, μ: 1514526, ~: 981456)
DN420Test:testMintToZeroReverts(uint256) (runs: 258, μ: 739930, ~: 664014)
DN420Test:testMixed(uint256) (runs: 258, μ: 10214241, ~: 6379210)
DN420Test:testSafeBatchTransferFromToERC1155Recipient(uint256) (runs: 258, μ: 2221345, ~: 2179908)
DN420Test:testSafeTransferFromToERC1155Recipient(uint256) (runs: 258, μ: 1720072, ~: 1473626)
DN420Test:testTransferFromToERC1155Recipient(uint256) (runs: 258, μ: 2879746, ~: 2866163)
DN420Test:testTransferMixedReverts(uint256) (runs: 258, μ: 4148311, ~: 3905610)
DN420Test:test__codesize() (gas: 67049)
MappingsTest:testAddressPairMapSetAndGet(address[2],address[2],uint256,uint256) (runs: 258, μ: 45763, ~: 47075)
MappingsTest:testBitmapSetAndGet(uint256) (runs: 258, μ: 453208, ~: 413769)
MappingsTest:testBitmapSetAndGet(uint256,uint256,bool,bool) (runs: 258, μ: 25592, ~: 26270)
Expand Down
62 changes: 29 additions & 33 deletions src/DN420.sol
Original file line number Diff line number Diff line change
Expand Up @@ -761,19 +761,17 @@ abstract contract DN420 {
if (!isApprovedForAll(from, by)) revert NotOwnerNorApproved();
}

{
Bitmap storage fromOwned = $.owned[from];
if (!_owns(fromOwned, id)) revert TransferFromIncorrectOwner();
_set(fromOwned, id, false);
_set($.owned[to], id, true);
}
Bitmap storage fromOwned = $.owned[from];
if (!_owns(fromOwned, id)) revert TransferFromIncorrectOwner();
_set(fromOwned, id, false);
_set($.owned[to], id, true);

uint256 unit = _unit();
AddressData storage fromAddressData = $.addressData[from];
AddressData storage toAddressData = $.addressData[to];
/// @solidity memory-safe-assembly
assembly {
let diff := or(shl(160, unit), shl(128, 1))
let diff := shl(128, or(shl(32, unit), 1))
sstore(fromAddressData.slot, sub(sload(fromAddressData.slot), diff))
let toPacked := sload(toAddressData.slot)
let toCheckpoint := and(0xffffffff, shr(96, toPacked))
Expand Down Expand Up @@ -826,35 +824,33 @@ abstract contract DN420 {
}

uint256 amount;
uint256 upTo;
AddressData storage fromAddressData = $.addressData[from];
AddressData storage toAddressData = $.addressData[to];
unchecked {
uint256 upTo;
AddressData storage fromAddressData = $.addressData[from];
AddressData storage toAddressData = $.addressData[to];
{
uint256 n = ids.length;
amount = n * _unit();
Bitmap storage fromOwned = $.owned[from];
Bitmap storage toOwned = $.owned[to];
while (n != 0) {
uint256 id = _get(ids, --n);
if (!_owns(fromOwned, id)) revert TransferFromIncorrectOwner();
_set(fromOwned, id, false);
_set(toOwned, id, true);
_afterNFTTransfer(from, to, id);
upTo = _max(upTo, id);
}
}
/// @solidity memory-safe-assembly
assembly {
let diff := or(shl(160, amount), shl(128, mload(ids)))
sstore(fromAddressData.slot, sub(sload(fromAddressData.slot), diff))
let toPacked := sload(toAddressData.slot)
let toCheckpoint := and(0xffffffff, shr(96, toPacked))
// forgefmt: disable-next-item
sstore(toAddressData.slot, add(diff,
xor(toPacked, shl(96, mul(gt(upTo, toCheckpoint), xor(upTo, toCheckpoint))))))
uint256 n = ids.length;
amount = n * _unit();
Bitmap storage fromOwned = $.owned[from];
Bitmap storage toOwned = $.owned[to];
while (n != 0) {
uint256 id = _get(ids, --n);
if (!_owns(fromOwned, id)) revert TransferFromIncorrectOwner();
_set(fromOwned, id, false);
_set(toOwned, id, true);
_afterNFTTransfer(from, to, id);
upTo = _max(upTo, id);
}
}
/// @solidity memory-safe-assembly
assembly {
let diff := shl(128, or(shl(32, amount), mload(ids)))
sstore(fromAddressData.slot, sub(sload(fromAddressData.slot), diff))
let toPacked := sload(toAddressData.slot)
let toCheckpoint := and(0xffffffff, shr(96, toPacked))
// forgefmt: disable-next-item
sstore(toAddressData.slot, add(diff,
xor(toPacked, shl(96, mul(gt(upTo, toCheckpoint), xor(upTo, toCheckpoint))))))
}
_batchTransferEmit(from, to, ids);
/// @solidity memory-safe-assembly
assembly {
Expand Down
115 changes: 59 additions & 56 deletions test/DN420.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,14 @@ contract DN420Test is SoladyTest {
}

struct _TestTemps {
address from;
uint88 aliceAux;
uint88 fromAux;
uint256[] aliceIds;
uint256[] bobIds;
uint256[] ids;
uint256[] oriIds;
uint256 balanceBefore;
uint256 id;
address[] owners;
uint256[] expectedBalances;
Expand Down Expand Up @@ -899,112 +904,110 @@ contract DN420Test is SoladyTest {
function testTransferMixedReverts(uint256) public {
dn.initializeDN420(0, address(this));

address from = _randomNonZeroAddress();
uint256 amount = _bound(_random(), 1, 10) * _WAD;
dn.mint(from, amount, "");

uint88 fromAux = uint88(_random());
dn.setAux(from, fromAux);
_testTransferMixedReverts(from);
_testTransferMixedReverts2(from);
_testTransferMixedReverts3(from);
assertEq(dn.getAux(from), fromAux);
_TestTemps memory t;
t.from = _randomNonZeroAddress();
dn.mint(t.from, _bound(_random(), 1, 10) * _WAD, "");

dn.setAux(t.from, t.fromAux = uint88(_random()));
_testTransferMixedReverts(t);
_testTransferMixedReverts2(t);
_testTransferMixedReverts3(t);
assertEq(dn.getAux(t.from), t.fromAux);
}

function _testTransferMixedReverts(address from) internal {
uint256 amount = dn.balanceOf(from);

function _testTransferMixedReverts(_TestTemps memory t) internal {
uint256 amount = dn.balanceOf(t.from);
if (_random() % 4 == 0) {
vm.expectRevert(DN420.TransferToZeroAddress.selector);
dn.mint(address(0), _random(), "");
vm.expectRevert(DN420.TransferToZeroAddress.selector);
dn.mintNext(address(0), _random(), "");
vm.expectRevert(DN420.TransferToZeroAddress.selector);
dn.transfer(address(0), amount);
vm.prank(from);
vm.prank(t.from);
dn.approve(address(this), type(uint256).max);
vm.expectRevert(DN420.TransferToZeroAddress.selector);
dn.transferFrom(from, address(0), amount);
dn.transferFrom(t.from, address(0), amount);
address to = _randomNonZeroAddress();
dn.transferFrom(from, to, amount);
dn.transferFrom(t.from, to, amount);
vm.prank(to);
dn.transfer(from, amount);
dn.transfer(t.from, amount);
}

if (_random() % 4 == 0) {
address by;
if (_random() % 8 > 0) by = _random() % 2 == 0 ? from : _randomNonZeroAddress();
if (_random() % 8 > 0) by = _random() % 2 == 0 ? t.from : _randomNonZeroAddress();
address to = _randomNonZeroAddress();
if (by == address(0) || by == from) {
_safeTransferFromNFT(by, from, to, 1);
if (by == address(0) || by == t.from) {
_safeTransferFromNFT(by, t.from, to, 1);
} else if (_random() % 2 == 0) {
vm.prank(from);
vm.prank(t.from);
dn.setApprovalForAll(by, true);
_safeTransferFromNFT(by, from, to, 1);
vm.prank(from);
_safeTransferFromNFT(by, t.from, to, 1);
vm.prank(t.from);
dn.setApprovalForAll(by, false);
} else {
vm.expectRevert(DN420.NotOwnerNorApproved.selector);
_safeTransferFromNFT(by, from, to, 1);
_safeTransferFromNFT(by, t.from, to, 1);
}
if (dn.owns(to, 1)) {
vm.prank(to);
_safeTransferFromNFT(to, to, from, 1);
_safeTransferFromNFT(to, to, t.from, 1);
}
}
}

function _testTransferMixedReverts2(address from) internal {
function _testTransferMixedReverts2(_TestTemps memory t) internal {
if (_random() % 4 == 0) {
uint256 id = _bound(_random(), 0, 256);
while (dn.owns(from, id)) id = _bound(_random(), 0, 256);
while (dn.owns(t.from, id)) id = _bound(_random(), 0, 256);
vm.expectRevert(DN420.TransferFromIncorrectOwner.selector);
_safeTransferFromNFT(from, from, _randomNonZeroAddress(), id);
_safeTransferFromNFT(t.from, t.from, _randomNonZeroAddress(), id);
}

while (_random() % 4 == 0) {
address to = _randomNonZeroAddress();
while (from == to) to = _randomNonZeroAddress();
uint256[] memory ids = dn.findOwnedIds(from);
if (ids.length < 2) break;
ids[0] = ids[_bound(_random(), 1, ids.length - 1)];
while (t.from == to) to = _randomNonZeroAddress();
t.ids = dn.findOwnedIds(t.from);
if (t.ids.length < 2) break;
t.ids[0] = t.ids[_bound(_random(), 1, t.ids.length - 1)];
vm.expectRevert(DN420.TransferFromIncorrectOwner.selector);
dn.safeBatchTransferFromNFTs(from, from, to, ids);
dn.safeBatchTransferFromNFTs(t.from, t.from, to, t.ids);
}
}

function _testTransferMixedReverts3(address from) internal {
function _testTransferMixedReverts3(_TestTemps memory t) internal {
if (_random() % 2 == 0) {
address to = _random() % 2 == 0 ? from : _randomNonZeroAddress();
uint256[] memory ids = dn.findOwnedIds(from);
ids[0] = _bound(_random(), 0, 256);
while (dn.owns(from, ids[0])) ids[0] = _bound(_random(), 0, 256);
address to = _random() % 2 == 0 ? t.from : _randomNonZeroAddress();
t.ids = dn.findOwnedIds(t.from);
t.ids[0] = _bound(_random(), 0, 256);
while (dn.owns(t.from, t.ids[0])) t.ids[0] = _bound(_random(), 0, 256);
vm.expectRevert(DN420.TransferFromIncorrectOwner.selector);
dn.safeBatchTransferFromNFTs(from, from, to, ids);
dn.safeBatchTransferFromNFTs(from, from, to, dn.findOwnedIds(from));
dn.safeBatchTransferFromNFTs(to, to, from, dn.findOwnedIds(to));
dn.safeBatchTransferFromNFTs(t.from, t.from, to, t.ids);
dn.safeBatchTransferFromNFTs(t.from, t.from, to, dn.findOwnedIds(t.from));
dn.safeBatchTransferFromNFTs(to, to, t.from, dn.findOwnedIds(to));

if (_random() % 2 == 0) {
ids = dn.findOwnedIds(from);
LibSort.sort(ids);
uint256 oriLength = ids.length;
ids = LibSort.union(ids, _randomSampleWithoutReplacements(ids));
if (ids.length > oriLength) {
if (from != to) {
t.ids = dn.findOwnedIds(t.from);
LibSort.sort(t.ids);
t.oriIds = t.ids;
t.ids = LibSort.union(t.ids, _randomSampleWithoutReplacements(t.ids));
if (t.ids.length > t.oriIds.length) {
if (t.from != to) {
vm.expectRevert(DN420.TransferFromIncorrectOwner.selector);
dn.safeBatchTransferFromNFTs(from, from, to, ids);
dn.safeBatchTransferFromNFTs(t.from, t.from, to, t.ids);
} else if (_random() % 2 == 0) {
uint256 balanceBefore = dn.balanceOf(from);
dn.safeBatchTransferFromNFTs(from, from, to, ids);
assertEq(dn.balanceOf(from), balanceBefore);
t.balanceBefore = dn.balanceOf(t.from);
dn.safeBatchTransferFromNFTs(t.from, t.from, to, t.ids);
assertEq(dn.balanceOf(t.from), t.balanceBefore);
} else {
uint256[] memory idsBefore = dn.findOwnedIds(from);
dn.safeBatchTransferFromNFTs(from, from, to, ids);
assertEq(dn.findOwnedIds(from), idsBefore);
t.oriIds = dn.findOwnedIds(t.from);
dn.safeBatchTransferFromNFTs(t.from, t.from, to, t.ids);
assertEq(dn.findOwnedIds(t.from), t.oriIds);
}
} else {
dn.safeBatchTransferFromNFTs(from, from, to, ids);
dn.safeBatchTransferFromNFTs(to, to, from, ids);
dn.safeBatchTransferFromNFTs(t.from, t.from, to, t.ids);
dn.safeBatchTransferFromNFTs(to, to, t.from, t.ids);
}
}
}
Expand Down

0 comments on commit 01e3f1e

Please sign in to comment.