From ecde265b3b0c67bf9979cb986ca071a6e16fa2f0 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Wed, 15 Jan 2025 13:27:59 +0000 Subject: [PATCH 1/3] Add automatic pullOwner --- src/DN404.sol | 8 ++++++++ test/DN404Mirror.t.sol | 25 +++++++++++++++++++++---- test/utils/mocks/MockDN404Ownable.sol | 9 +++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/DN404.sol b/src/DN404.sol index 0e888f9..3689e87 100644 --- a/src/DN404.sol +++ b/src/DN404.sol @@ -249,6 +249,14 @@ abstract contract DN404 { mstore(0x00, 0xd125259c) // `LinkMirrorContractFailed()`. revert(0x1c, 0x04) } + // Query `owner()` on this contract, and if it is non-zero, call `pullOwner()` on the mirror. + /// This allows for any Ownable (e.g. OpenZeppelin, Solady). + mstore(0x00, 0x8da5cb5b) // `owner()`. + let t := staticcall(gas(), address(), 0x1c, 0x04, 0x00, 0x20) + if and(lt(iszero(shl(96, mload(0x00))), gt(returndatasize(), 0x1f)), t) { + mstore(0x00, 0x6cef16e6) // `pullOwner()`. + if iszero(call(gas(), mirror, 0, 0x1c, 0x04, 0x00, 0x00)) { revert(0x00, 0x00) } + } } $.nextTokenId = uint32(_toUint(_useOneIndexed())); diff --git a/test/DN404Mirror.t.sol b/test/DN404Mirror.t.sol index 4c09229..86a5b08 100644 --- a/test/DN404Mirror.t.sol +++ b/test/DN404Mirror.t.sol @@ -293,19 +293,36 @@ contract DN404MirrorTest is SoladyTest { assertEq(mirror.owner(), address(0)); } - function testPullOwnerWithOwnable() public { - MockDN404Ownable dnOwnable = new MockDN404Ownable(); + function testAutomaticPullOwnerWithOwnable() public { + MockDN404Ownable dnOwnable = new MockDN404Ownable(address(0)); dnOwnable.initializeDN404(1000, address(this), address(mirror)); + assertEq(mirror.owner(), address(0)); + mirror.pullOwner(); + assertEq(mirror.owner(), address(0)); + + dnOwnable.initializeOwner(address(this)); + assertEq(mirror.owner(), address(0)); + mirror.pullOwner(); + assertEq(mirror.owner(), address(this)); + address newOwner = address(123); dnOwnable.transferOwnership(newOwner); - assertEq(mirror.owner(), address(0)); vm.expectEmit(true, true, true, true); - emit OwnershipTransferred(address(0), newOwner); + emit OwnershipTransferred(address(this), newOwner); mirror.pullOwner(); assertEq(mirror.owner(), newOwner); } + function testAutomaticPullOwnerWithOwnable2() public { + MockDN404Ownable dnOwnable = new MockDN404Ownable(address(this)); + assertEq(mirror.owner(), address(0)); + vm.expectEmit(true, true, true, true); + emit OwnershipTransferred(address(0), address(this)); + dnOwnable.initializeDN404(1000, address(this), address(mirror)); + assertEq(mirror.owner(), address(this)); + } + function testFnSelectorNotRecognized() public { (bool success, bytes memory result) = address(dn).call(abi.encodeWithSignature("nonSupportedFunction123()")); diff --git a/test/utils/mocks/MockDN404Ownable.sol b/test/utils/mocks/MockDN404Ownable.sol index 050288a..e9ba63c 100644 --- a/test/utils/mocks/MockDN404Ownable.sol +++ b/test/utils/mocks/MockDN404Ownable.sol @@ -5,7 +5,12 @@ import "./MockDN404.sol"; import {Ownable} from "solady/auth/Ownable.sol"; contract MockDN404Ownable is MockDN404, Ownable { - constructor() { - _initializeOwner(msg.sender); + constructor(address initialOwner) { + if (initialOwner != address(0)) { + _initializeOwner(initialOwner); + } + } + function initializeOwner(address initialOwner) public { + _initializeOwner(initialOwner); } } From 0e2a4630944b97e91f0dcd04f887e547c068cb7c Mon Sep 17 00:00:00 2001 From: Vectorized Date: Wed, 15 Jan 2025 13:28:08 +0000 Subject: [PATCH 2/3] T --- test/utils/mocks/MockDN404Ownable.sol | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/utils/mocks/MockDN404Ownable.sol b/test/utils/mocks/MockDN404Ownable.sol index e9ba63c..5956cec 100644 --- a/test/utils/mocks/MockDN404Ownable.sol +++ b/test/utils/mocks/MockDN404Ownable.sol @@ -5,12 +5,13 @@ import "./MockDN404.sol"; import {Ownable} from "solady/auth/Ownable.sol"; contract MockDN404Ownable is MockDN404, Ownable { - constructor(address initialOwner) { - if (initialOwner != address(0)) { - _initializeOwner(initialOwner); - } - } + constructor(address initialOwner) { + if (initialOwner != address(0)) { + _initializeOwner(initialOwner); + } + } + function initializeOwner(address initialOwner) public { - _initializeOwner(initialOwner); + _initializeOwner(initialOwner); } } From 0d997f9b3a44227a965bb807430cf7da00e6b4e4 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Wed, 15 Jan 2025 13:31:36 +0000 Subject: [PATCH 3/3] T --- src/DN404.sol | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/DN404.sol b/src/DN404.sol index 3689e87..b1ed1ee 100644 --- a/src/DN404.sol +++ b/src/DN404.sol @@ -250,13 +250,12 @@ abstract contract DN404 { revert(0x1c, 0x04) } // Query `owner()` on this contract, and if it is non-zero, call `pullOwner()` on the mirror. - /// This allows for any Ownable (e.g. OpenZeppelin, Solady). - mstore(0x00, 0x8da5cb5b) // `owner()`. - let t := staticcall(gas(), address(), 0x1c, 0x04, 0x00, 0x20) - if and(lt(iszero(shl(96, mload(0x00))), gt(returndatasize(), 0x1f)), t) { - mstore(0x00, 0x6cef16e6) // `pullOwner()`. - if iszero(call(gas(), mirror, 0, 0x1c, 0x04, 0x00, 0x00)) { revert(0x00, 0x00) } - } + // This allows for any Ownable (e.g. OpenZeppelin, Solady). + mstore(0x00, 0x8da5cb5b6cef16e6) // `owner()` and `pullOwner()`. + if and( + lt(iszero(shl(96, mload(0x20))), gt(returndatasize(), 0x1f)), + staticcall(gas(), address(), 0x18, 0x04, 0x20, 0x20) + ) { if iszero(call(gas(), mirror, 0, 0x1c, 0x04, 0x00, 0x00)) { revert(0x00, 0x00) } } } $.nextTokenId = uint32(_toUint(_useOneIndexed()));