-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
270 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@cartesi/rollups": major | ||
--- | ||
|
||
Added ENS Portal. | ||
Added a new input encoding for ENS inputs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// (c) Cartesi and individual authors (see AUTHORS) | ||
// SPDX-License-Identifier: Apache-2.0 (see LICENSE) | ||
|
||
pragma solidity ^0.8.8; | ||
|
||
import {ENS} from "@ensdomains/ens-contracts/contracts/registry/ENS.sol"; | ||
import {AddrResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/AddrResolver.sol"; | ||
|
||
library LibENS { | ||
/// @notice Resolve ENS node to address | ||
/// @param ens The ENS registry | ||
/// @param node The ENS node | ||
/// @return The address that ENS node resolves to | ||
function resolveToAddress( | ||
ENS ens, | ||
bytes32 node | ||
) internal view returns (address) { | ||
AddrResolver resolver = AddrResolver(ens.resolver(node)); | ||
return resolver.addr(node); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// (c) Cartesi and individual authors (see AUTHORS) | ||
// SPDX-License-Identifier: Apache-2.0 (see LICENSE) | ||
|
||
pragma solidity ^0.8.8; | ||
|
||
import {ENS} from "@ensdomains/ens-contracts/contracts/registry/ENS.sol"; | ||
|
||
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; | ||
|
||
import {IENSPortal} from "./IENSPortal.sol"; | ||
import {Portal} from "./Portal.sol"; | ||
import {IInputBox} from "../inputs/IInputBox.sol"; | ||
import {InputEncoding} from "../common/InputEncoding.sol"; | ||
import {LibENS} from "../library/LibENS.sol"; | ||
|
||
/// @title ENS Portal | ||
/// | ||
/// @notice This contract allows anyone to send input to the InputBox with ENS | ||
contract ENSPortal is IENSPortal, Portal { | ||
using LibENS for ENS; | ||
|
||
ENS immutable _ens; | ||
|
||
/// @notice Constructs the portal. | ||
/// @param inputBox The input box used by the portal | ||
/// @param ens The ENS registry | ||
constructor(IInputBox inputBox, ENS ens) Portal(inputBox) { | ||
_ens = ens; | ||
} | ||
|
||
function sendInputWithENS( | ||
address appContract, | ||
bytes32 node, | ||
bytes calldata name, | ||
bytes calldata execLayerData | ||
) external override { | ||
address resolution = _ens.resolveToAddress(node); | ||
|
||
if (resolution != msg.sender) { | ||
revert AddressResolutionMismatch(resolution, msg.sender); | ||
} | ||
|
||
bytes memory payload = InputEncoding.encodeENSInput( | ||
node, | ||
name, | ||
execLayerData | ||
); | ||
|
||
_inputBox.addInput(appContract, payload); | ||
} | ||
|
||
function getENS() external view override returns (ENS) { | ||
return _ens; | ||
} | ||
|
||
function supportsInterface( | ||
bytes4 interfaceId | ||
) public view virtual override(IERC165, Portal) returns (bool) { | ||
return | ||
interfaceId == type(IENSPortal).interfaceId || | ||
super.supportsInterface(interfaceId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// (c) Cartesi and individual authors (see AUTHORS) | ||
// SPDX-License-Identifier: Apache-2.0 (see LICENSE) | ||
|
||
pragma solidity ^0.8.8; | ||
|
||
import {IPortal} from "./IPortal.sol"; | ||
import {ENS} from "@ensdomains/ens-contracts/contracts/registry/ENS.sol"; | ||
|
||
/// @title ENS Portal interface | ||
interface IENSPortal is IPortal { | ||
// Errors | ||
|
||
/// @notice The provided ENS node does not resolve to the sender address. | ||
/// @param resolution The address that the ENS node resolves to | ||
/// @param sender The sender address | ||
error AddressResolutionMismatch(address resolution, address sender); | ||
|
||
// Permissionless functions | ||
|
||
/// @notice Send input to InputBox with ENS. | ||
/// @param appContract The application contract address | ||
/// @param node The ENS node | ||
/// @param name The ENS name | ||
/// @param execLayerData Additional data to be interpreted by | ||
/// the execution layer. The data may include the ENS name | ||
function sendInputWithENS( | ||
address appContract, | ||
bytes32 node, | ||
bytes calldata name, | ||
bytes calldata execLayerData | ||
) external; | ||
|
||
/// @notice Get the ENS registry used by this portal. | ||
/// @return The ENS registry | ||
function getENS() external view returns (ENS); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// (c) Cartesi and individual authors (see AUTHORS) | ||
// SPDX-License-Identifier: Apache-2.0 (see LICENSE) | ||
|
||
pragma solidity ^0.8.22; | ||
|
||
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; | ||
|
||
import {ENS} from "@ensdomains/ens-contracts/contracts/registry/ENS.sol"; | ||
import {AddrResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/AddrResolver.sol"; | ||
|
||
import {ENSPortal} from "contracts/portals/ENSPortal.sol"; | ||
import {IENSPortal} from "contracts/portals/IENSPortal.sol"; | ||
import {IInputBox} from "contracts/inputs/IInputBox.sol"; | ||
import {IPortal} from "contracts/portals/IPortal.sol"; | ||
import {InputEncoding} from "contracts/common/InputEncoding.sol"; | ||
|
||
import {ERC165Test} from "../util/ERC165Test.sol"; | ||
|
||
contract ENSPortalTest is ERC165Test { | ||
IInputBox _inputBox; | ||
IENSPortal _portal; | ||
ENS _ens; | ||
AddrResolver _resolver; | ||
|
||
address _inputSender; | ||
address _appContract; | ||
bytes4[] _interfaceIds; | ||
|
||
bytes32 constant _node = keccak256("user.eth"); | ||
|
||
function setUp() public { | ||
_inputSender = _newAddr(); | ||
_appContract = _newAddr(); | ||
_inputBox = IInputBox(_newAddr()); | ||
_ens = ENS(_newAddr()); | ||
_portal = new ENSPortal(_inputBox, _ens); | ||
_resolver = AddrResolver(_newAddr()); | ||
|
||
vm.mockCall( | ||
address(_ens), | ||
abi.encodeCall(ENS.resolver, (_node)), | ||
abi.encode(_resolver) | ||
); | ||
vm.mockCall( | ||
address(_resolver), | ||
abi.encodeWithSignature("addr(bytes32)", (_node)), | ||
abi.encode(_inputSender) | ||
); | ||
|
||
_interfaceIds.push(type(IENSPortal).interfaceId); | ||
_interfaceIds.push(type(IPortal).interfaceId); | ||
} | ||
|
||
function getERC165Contract() public view override returns (IERC165) { | ||
return _portal; | ||
} | ||
|
||
function getSupportedInterfaces() | ||
public | ||
view | ||
override | ||
returns (bytes4[] memory) | ||
{ | ||
return _interfaceIds; | ||
} | ||
|
||
function testGetInputBox() public view { | ||
assertEq(address(_portal.getInputBox()), address(_inputBox)); | ||
} | ||
|
||
function testGetENS() public view { | ||
assertEq(address(_portal.getENS()), address(_ens)); | ||
} | ||
|
||
function testAddressResolutionMismatch( | ||
address incorrectSender, | ||
bytes calldata name, | ||
bytes calldata execLayerData | ||
) public { | ||
vm.assume(incorrectSender != _inputSender); | ||
|
||
vm.expectRevert( | ||
abi.encodeWithSelector( | ||
IENSPortal.AddressResolutionMismatch.selector, | ||
_inputSender, | ||
incorrectSender | ||
) | ||
); | ||
vm.prank(incorrectSender); | ||
_portal.sendInputWithENS(_appContract, _node, name, execLayerData); | ||
} | ||
|
||
function testSendInput( | ||
bytes calldata name, | ||
bytes calldata execLayerData | ||
) public { | ||
bytes memory payload = _encodePayload(_node, name, execLayerData); | ||
bytes memory addInput = _encodeAddInput(payload); | ||
|
||
vm.mockCall(address(_inputBox), addInput, abi.encode(bytes32(0))); | ||
vm.expectCall(address(_inputBox), addInput, 1); | ||
vm.prank(_inputSender); | ||
_portal.sendInputWithENS(_appContract, _node, name, execLayerData); | ||
} | ||
|
||
function _encodePayload( | ||
bytes32 node, | ||
bytes calldata name, | ||
bytes calldata execLayerData | ||
) internal pure returns (bytes memory) { | ||
return InputEncoding.encodeENSInput(node, name, execLayerData); | ||
} | ||
|
||
function _encodeAddInput( | ||
bytes memory payload | ||
) internal view returns (bytes memory) { | ||
return abi.encodeCall(IInputBox.addInput, (_appContract, payload)); | ||
} | ||
} |