diff --git a/onchain/rollups/.changeset/pink-penguins-kiss.md b/onchain/rollups/.changeset/pink-penguins-kiss.md new file mode 100644 index 00000000..09070503 --- /dev/null +++ b/onchain/rollups/.changeset/pink-penguins-kiss.md @@ -0,0 +1,5 @@ +--- +"@cartesi/rollups": major +--- + +Comply with Solidity style guide. diff --git a/onchain/rollups/contracts/consensus/authority/AuthorityFactory.sol b/onchain/rollups/contracts/consensus/authority/AuthorityFactory.sol index 8240d5bf..c512d7af 100644 --- a/onchain/rollups/contracts/consensus/authority/AuthorityFactory.sol +++ b/onchain/rollups/contracts/consensus/authority/AuthorityFactory.sol @@ -12,37 +12,37 @@ import {Authority} from "./Authority.sol"; /// @notice Allows anyone to reliably deploy a new `Authority` contract. contract AuthorityFactory is IAuthorityFactory { function newAuthority( - address _authorityOwner + address authorityOwner ) external override returns (Authority) { - Authority authority = new Authority(_authorityOwner); + Authority authority = new Authority(authorityOwner); - emit AuthorityCreated(_authorityOwner, authority); + emit AuthorityCreated(authorityOwner, authority); return authority; } function newAuthority( - address _authorityOwner, - bytes32 _salt + address authorityOwner, + bytes32 salt ) external override returns (Authority) { - Authority authority = new Authority{salt: _salt}(_authorityOwner); + Authority authority = new Authority{salt: salt}(authorityOwner); - emit AuthorityCreated(_authorityOwner, authority); + emit AuthorityCreated(authorityOwner, authority); return authority; } function calculateAuthorityAddress( - address _authorityOwner, - bytes32 _salt + address authorityOwner, + bytes32 salt ) external view override returns (address) { return Create2.computeAddress( - _salt, + salt, keccak256( abi.encodePacked( type(Authority).creationCode, - abi.encode(_authorityOwner) + abi.encode(authorityOwner) ) ) ); diff --git a/onchain/rollups/contracts/consensus/authority/IAuthorityFactory.sol b/onchain/rollups/contracts/consensus/authority/IAuthorityFactory.sol index d5df1bea..d0c0d49b 100644 --- a/onchain/rollups/contracts/consensus/authority/IAuthorityFactory.sol +++ b/onchain/rollups/contracts/consensus/authority/IAuthorityFactory.sol @@ -18,29 +18,29 @@ interface IAuthorityFactory { // Permissionless functions /// @notice Deploy a new authority. - /// @param _authorityOwner The initial authority owner + /// @param authorityOwner The initial authority owner /// @return The authority /// @dev On success, MUST emit an `AuthorityCreated` event. - function newAuthority(address _authorityOwner) external returns (Authority); + function newAuthority(address authorityOwner) external returns (Authority); /// @notice Deploy a new authority deterministically. - /// @param _authorityOwner The initial authority owner - /// @param _salt The salt used to deterministically generate the authority address + /// @param authorityOwner The initial authority owner + /// @param salt The salt used to deterministically generate the authority address /// @return The authority /// @dev On success, MUST emit an `AuthorityCreated` event. function newAuthority( - address _authorityOwner, - bytes32 _salt + address authorityOwner, + bytes32 salt ) external returns (Authority); /// @notice Calculate the address of an authority to be deployed deterministically. - /// @param _authorityOwner The initial authority owner - /// @param _salt The salt used to deterministically generate the authority address + /// @param authorityOwner The initial authority owner + /// @param salt The salt used to deterministically generate the authority address /// @return The deterministic authority address - /// @dev Beware that only the `newAuthority` function with the `_salt` parameter + /// @dev Beware that only the `newAuthority` function with the `salt` parameter /// is able to deterministically deploy an authority. function calculateAuthorityAddress( - address _authorityOwner, - bytes32 _salt + address authorityOwner, + bytes32 salt ) external view returns (address); } diff --git a/onchain/rollups/contracts/dapp/Application.sol b/onchain/rollups/contracts/dapp/Application.sol index 9f797b88..77bf3bc2 100644 --- a/onchain/rollups/contracts/dapp/Application.sol +++ b/onchain/rollups/contracts/dapp/Application.sol @@ -76,84 +76,98 @@ contract Application is using LibInputRange for InputRange; using Address for address; - /// @notice Raised when executing an already executed voucher. - error VoucherReexecutionNotAllowed(); - - /// @notice Raised when the transfer fails. - error EtherTransferFailed(); - - /// @notice Raised when a mehtod is not called by application itself. - error OnlyApplication(); - /// @notice The initial machine state hash. /// @dev See the `getTemplateHash` function. - bytes32 internal immutable templateHash; + bytes32 internal immutable _templateHash; /// @notice The executed voucher bitmask, which keeps track of which vouchers /// were executed already in order to avoid re-execution. /// @dev See the `wasVoucherExecuted` function. - mapping(uint256 => BitMaps.BitMap) internal voucherBitmaps; + mapping(uint256 => BitMaps.BitMap) internal _voucherBitmaps; /// @notice The current consensus contract. /// @dev See the `getConsensus` and `migrateToConsensus` functions. - IConsensus internal consensus; + IConsensus internal _consensus; /// @notice The input box contract. /// @dev See the `getInputBox` function. - IInputBox internal immutable inputBox; + IInputBox internal immutable _inputBox; /// @notice The input relays. /// @dev See the `getInputRelays` function. - IInputRelay[] internal inputRelays; + IInputRelay[] internal _inputRelays; + + /// @notice Raised when executing an already executed voucher. + error VoucherReexecutionNotAllowed(); + + /// @notice Raised when the transfer fails. + error EtherTransferFailed(); + + /// @notice Raised when a mehtod is not called by application itself. + error OnlyApplication(); /// @notice Creates an `Application` contract. - /// @param _consensus The initial consensus contract - /// @param _inputBox The input box contract - /// @param _inputRelays The input relays - /// @param _initialOwner The initial application owner - /// @param _templateHash The initial machine state hash + /// @param consensus The initial consensus contract + /// @param inputBox The input box contract + /// @param inputRelays The input relays + /// @param initialOwner The initial application owner + /// @param templateHash The initial machine state hash constructor( - IConsensus _consensus, - IInputBox _inputBox, - IInputRelay[] memory _inputRelays, - address _initialOwner, - bytes32 _templateHash - ) Ownable(_initialOwner) { - templateHash = _templateHash; - consensus = _consensus; - inputBox = _inputBox; - for (uint256 i; i < _inputRelays.length; ++i) { - inputRelays.push(_inputRelays[i]); + IConsensus consensus, + IInputBox inputBox, + IInputRelay[] memory inputRelays, + address initialOwner, + bytes32 templateHash + ) Ownable(initialOwner) { + _templateHash = templateHash; + _consensus = consensus; + _inputBox = inputBox; + for (uint256 i; i < inputRelays.length; ++i) { + _inputRelays.push(inputRelays[i]); } } - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC1155Holder, IERC165) returns (bool) { - return - interfaceId == type(IApplication).interfaceId || - interfaceId == type(IERC721Receiver).interfaceId || - super.supportsInterface(interfaceId); + /// @notice Accept Ether transfers. + /// @dev If you wish to transfer Ether to an application while informing + /// the backend of it, then please do so through the Ether portal contract. + receive() external payable {} + + /// @notice Transfer some amount of Ether to some recipient. + /// @param receiver The address which will receive the amount of Ether + /// @param value The amount of Ether to be transferred in Wei + /// @dev This function can only be called by the application itself through vouchers. + /// If this method is not called by application itself, `OnlyApplication` error is raised. + /// If the transfer fails, `EtherTransferFailed` error is raised. + function withdrawEther(address receiver, uint256 value) external { + if (msg.sender != address(this)) { + revert OnlyApplication(); + } + + (bool sent, ) = receiver.call{value: value}(""); + + if (!sent) { + revert EtherTransferFailed(); + } } function executeVoucher( - address _destination, - bytes calldata _payload, - Proof calldata _proof + address destination, + bytes calldata payload, + Proof calldata proof ) external override nonReentrant { - uint256 inputIndex = _proof.calculateInputIndex(); + uint256 inputIndex = proof.calculateInputIndex(); - if (!_proof.inputRange.contains(inputIndex)) { - revert InputIndexOutOfRange(inputIndex, _proof.inputRange); + if (!proof.inputRange.contains(inputIndex)) { + revert InputIndexOutOfRange(inputIndex, proof.inputRange); } - bytes32 epochHash = getEpochHash(_proof.inputRange); + bytes32 epochHash = _getEpochHash(proof.inputRange); // reverts if proof isn't valid - _proof.validity.validateVoucher(_destination, _payload, epochHash); + proof.validity.validateVoucher(destination, payload, epochHash); - uint256 outputIndexWithinInput = _proof.validity.outputIndexWithinInput; - BitMaps.BitMap storage bitmap = voucherBitmaps[outputIndexWithinInput]; + uint256 outputIndexWithinInput = proof.validity.outputIndexWithinInput; + BitMaps.BitMap storage bitmap = _voucherBitmaps[outputIndexWithinInput]; // check if voucher has been executed if (bitmap.get(inputIndex)) { @@ -161,53 +175,53 @@ contract Application is } // execute voucher - _destination.functionCall(_payload); + destination.functionCall(payload); // mark it as executed and emit event bitmap.set(inputIndex); emit VoucherExecuted(inputIndex, outputIndexWithinInput); } + function migrateToConsensus( + IConsensus newConsensus + ) external override onlyOwner { + _consensus = newConsensus; + emit NewConsensus(newConsensus); + } + function wasVoucherExecuted( - uint256 _inputIndex, - uint256 _outputIndexWithinInput + uint256 inputIndex, + uint256 outputIndexWithinInput ) external view override returns (bool) { - return voucherBitmaps[_outputIndexWithinInput].get(_inputIndex); + return _voucherBitmaps[outputIndexWithinInput].get(inputIndex); } function validateNotice( - bytes calldata _notice, - Proof calldata _proof + bytes calldata notice, + Proof calldata proof ) external view override { - uint256 inputIndex = _proof.calculateInputIndex(); + uint256 inputIndex = proof.calculateInputIndex(); - if (!_proof.inputRange.contains(inputIndex)) { - revert InputIndexOutOfRange(inputIndex, _proof.inputRange); + if (!proof.inputRange.contains(inputIndex)) { + revert InputIndexOutOfRange(inputIndex, proof.inputRange); } - bytes32 epochHash = getEpochHash(_proof.inputRange); + bytes32 epochHash = _getEpochHash(proof.inputRange); // reverts if proof isn't valid - _proof.validity.validateNotice(_notice, epochHash); - } - - function migrateToConsensus( - IConsensus _newConsensus - ) external override onlyOwner { - consensus = _newConsensus; - emit NewConsensus(_newConsensus); + proof.validity.validateNotice(notice, epochHash); } function getTemplateHash() external view override returns (bytes32) { - return templateHash; + return _templateHash; } function getConsensus() external view override returns (IConsensus) { - return consensus; + return _consensus; } function getInputBox() external view override returns (IInputBox) { - return inputBox; + return _inputBox; } function getInputRelays() @@ -216,39 +230,25 @@ contract Application is override returns (IInputRelay[] memory) { - return inputRelays; + return _inputRelays; } - /// @notice Accept Ether transfers. - /// @dev If you wish to transfer Ether to an application while informing - /// the backend of it, then please do so through the Ether portal contract. - receive() external payable {} - - /// @notice Transfer some amount of Ether to some recipient. - /// @param _receiver The address which will receive the amount of Ether - /// @param _value The amount of Ether to be transferred in Wei - /// @dev This function can only be called by the application itself through vouchers. - /// If this method is not called by application itself, `OnlyApplication` error is raised. - /// If the transfer fails, `EtherTransferFailed` error is raised. - function withdrawEther(address _receiver, uint256 _value) external { - if (msg.sender != address(this)) { - revert OnlyApplication(); - } - - (bool sent, ) = _receiver.call{value: _value}(""); - - if (!sent) { - revert EtherTransferFailed(); - } + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(ERC1155Holder, IERC165) returns (bool) { + return + interfaceId == type(IApplication).interfaceId || + interfaceId == type(IERC721Receiver).interfaceId || + super.supportsInterface(interfaceId); } /// @notice Get the epoch hash regarding the given input range /// and the application from the current consensus. /// @param inputRange The input range /// @return The epoch hash - function getEpochHash( + function _getEpochHash( InputRange calldata inputRange ) internal view returns (bytes32) { - return consensus.getEpochHash(address(this), inputRange); + return _consensus.getEpochHash(address(this), inputRange); } } diff --git a/onchain/rollups/contracts/dapp/ApplicationFactory.sol b/onchain/rollups/contracts/dapp/ApplicationFactory.sol index 123f9bd7..b1b9d27d 100644 --- a/onchain/rollups/contracts/dapp/ApplicationFactory.sol +++ b/onchain/rollups/contracts/dapp/ApplicationFactory.sol @@ -15,26 +15,26 @@ import {Application} from "./Application.sol"; /// @notice Allows anyone to reliably deploy a new `Application` contract. contract ApplicationFactory is IApplicationFactory { function newApplication( - IConsensus _consensus, - IInputBox _inputBox, - IInputRelay[] memory _inputRelays, - address _appOwner, - bytes32 _templateHash + IConsensus consensus, + IInputBox inputBox, + IInputRelay[] memory inputRelays, + address appOwner, + bytes32 templateHash ) external override returns (Application) { Application app = new Application( - _consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash + consensus, + inputBox, + inputRelays, + appOwner, + templateHash ); emit ApplicationCreated( - _consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash, + consensus, + inputBox, + inputRelays, + appOwner, + templateHash, app ); @@ -42,27 +42,27 @@ contract ApplicationFactory is IApplicationFactory { } function newApplication( - IConsensus _consensus, - IInputBox _inputBox, - IInputRelay[] memory _inputRelays, - address _appOwner, - bytes32 _templateHash, - bytes32 _salt + IConsensus consensus, + IInputBox inputBox, + IInputRelay[] memory inputRelays, + address appOwner, + bytes32 templateHash, + bytes32 salt ) external override returns (Application) { - Application app = new Application{salt: _salt}( - _consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash + Application app = new Application{salt: salt}( + consensus, + inputBox, + inputRelays, + appOwner, + templateHash ); emit ApplicationCreated( - _consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash, + consensus, + inputBox, + inputRelays, + appOwner, + templateHash, app ); @@ -70,25 +70,25 @@ contract ApplicationFactory is IApplicationFactory { } function calculateApplicationAddress( - IConsensus _consensus, - IInputBox _inputBox, - IInputRelay[] memory _inputRelays, - address _appOwner, - bytes32 _templateHash, - bytes32 _salt + IConsensus consensus, + IInputBox inputBox, + IInputRelay[] memory inputRelays, + address appOwner, + bytes32 templateHash, + bytes32 salt ) external view override returns (address) { return Create2.computeAddress( - _salt, + salt, keccak256( abi.encodePacked( type(Application).creationCode, abi.encode( - _consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash + consensus, + inputBox, + inputRelays, + appOwner, + templateHash ) ) ) diff --git a/onchain/rollups/contracts/dapp/IApplication.sol b/onchain/rollups/contracts/dapp/IApplication.sol index 4cf2e3e6..d41e434d 100644 --- a/onchain/rollups/contracts/dapp/IApplication.sol +++ b/onchain/rollups/contracts/dapp/IApplication.sol @@ -15,14 +15,6 @@ import {InputRange} from "../common/InputRange.sol"; /// @title Application interface interface IApplication is IERC721Receiver, IERC1155Receiver { - // Errors - - /// @notice Could not validate an output because - /// the input that generated it is outside the given input range. - /// @param inputIndex The input index - /// @param inputRange The input range - error InputIndexOutOfRange(uint256 inputIndex, InputRange inputRange); - // Events /// @notice The application has migrated to another consensus contract. @@ -35,12 +27,20 @@ interface IApplication is IERC721Receiver, IERC1155Receiver { /// @param outputIndexWithinInput The index of the voucher amongst all outputs emitted by the input event VoucherExecuted(uint256 inputIndex, uint256 outputIndexWithinInput); + // Errors + + /// @notice Could not validate an output because + /// the input that generated it is outside the given input range. + /// @param inputIndex The input index + /// @param inputRange The input range + error InputIndexOutOfRange(uint256 inputIndex, InputRange inputRange); + // Permissioned functions /// @notice Migrate the application to a new consensus. - /// @param _newConsensus The new consensus + /// @param newConsensus The new consensus /// @dev Can only be called by the application owner. - function migrateToConsensus(IConsensus _newConsensus) external; + function migrateToConsensus(IConsensus newConsensus) external; // Permissionless functions @@ -48,34 +48,34 @@ interface IApplication is IERC721Receiver, IERC1155Receiver { /// Reverts if the proof is invalid. /// Reverts if the voucher was already successfully executed. /// Propagates any error raised by the low-level call. - /// @param _destination The address that will receive the payload through a message call - /// @param _payload The payload, which—in the case of Solidity contracts—encodes a function call - /// @param _proof The proof used to validate the voucher against + /// @param destination The address that will receive the payload through a message call + /// @param payload The payload, which—in the case of Solidity contracts—encodes a function call + /// @param proof The proof used to validate the voucher against /// a claim submitted by the current consensus contract /// @dev On a successful execution, emits a `VoucherExecuted` event. function executeVoucher( - address _destination, - bytes calldata _payload, - Proof calldata _proof + address destination, + bytes calldata payload, + Proof calldata proof ) external; /// @notice Check whether a voucher has been executed. - /// @param _inputIndex The index of the input in the input box - /// @param _outputIndexWithinInput The index of output emitted by the input + /// @param inputIndex The index of the input in the input box + /// @param outputIndexWithinInput The index of output emitted by the input /// @return Whether the voucher has been executed before function wasVoucherExecuted( - uint256 _inputIndex, - uint256 _outputIndexWithinInput + uint256 inputIndex, + uint256 outputIndexWithinInput ) external view returns (bool); /// @notice Validate a notice. /// Reverts if the proof is invalid. - /// @param _notice The notice - /// @param _proof The proof used to validate the notice against + /// @param notice The notice + /// @param proof The proof used to validate the notice against /// a claim submitted by the current consensus contract function validateNotice( - bytes calldata _notice, - Proof calldata _proof + bytes calldata notice, + Proof calldata proof ) external view; /// @notice Get the application's template hash. diff --git a/onchain/rollups/contracts/dapp/IApplicationFactory.sol b/onchain/rollups/contracts/dapp/IApplicationFactory.sol index 37410a7a..a8bc452e 100644 --- a/onchain/rollups/contracts/dapp/IApplicationFactory.sol +++ b/onchain/rollups/contracts/dapp/IApplicationFactory.sol @@ -32,55 +32,55 @@ interface IApplicationFactory { // Permissionless functions /// @notice Deploy a new application. - /// @param _consensus The initial consensus contract - /// @param _inputBox The input box contract - /// @param _inputRelays The input relays - /// @param _appOwner The initial application owner - /// @param _templateHash The initial machine state hash + /// @param consensus The initial consensus contract + /// @param inputBox The input box contract + /// @param inputRelays The input relays + /// @param appOwner The initial application owner + /// @param templateHash The initial machine state hash /// @return The application /// @dev On success, MUST emit an `ApplicationCreated` event. function newApplication( - IConsensus _consensus, - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash + IConsensus consensus, + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash ) external returns (Application); /// @notice Deploy a new application deterministically. - /// @param _consensus The initial consensus contract - /// @param _inputBox The input box contract - /// @param _inputRelays The input relays - /// @param _appOwner The initial application owner - /// @param _templateHash The initial machine state hash - /// @param _salt The salt used to deterministically generate the application address + /// @param consensus The initial consensus contract + /// @param inputBox The input box contract + /// @param inputRelays The input relays + /// @param appOwner The initial application owner + /// @param templateHash The initial machine state hash + /// @param salt The salt used to deterministically generate the application address /// @return The application /// @dev On success, MUST emit an `ApplicationCreated` event. function newApplication( - IConsensus _consensus, - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash, - bytes32 _salt + IConsensus consensus, + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash, + bytes32 salt ) external returns (Application); /// @notice Calculate the address of an application to be deployed deterministically. - /// @param _consensus The initial consensus contract - /// @param _inputBox The input box contract - /// @param _inputRelays The input relays - /// @param _appOwner The initial application owner - /// @param _templateHash The initial machine state hash - /// @param _salt The salt used to deterministically generate the application address + /// @param consensus The initial consensus contract + /// @param inputBox The input box contract + /// @param inputRelays The input relays + /// @param appOwner The initial application owner + /// @param templateHash The initial machine state hash + /// @param salt The salt used to deterministically generate the application address /// @return The deterministic application address - /// @dev Beware that only the `newApplication` function with the `_salt` parameter + /// @dev Beware that only the `newApplication` function with the `salt` parameter /// is able to deterministically deploy an application. function calculateApplicationAddress( - IConsensus _consensus, - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash, - bytes32 _salt + IConsensus consensus, + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash, + bytes32 salt ) external view returns (address); } diff --git a/onchain/rollups/contracts/inputs/IInputBox.sol b/onchain/rollups/contracts/inputs/IInputBox.sol index 3d38372d..84c4bb63 100644 --- a/onchain/rollups/contracts/inputs/IInputBox.sol +++ b/onchain/rollups/contracts/inputs/IInputBox.sol @@ -19,29 +19,29 @@ interface IInputBox { ); /// @notice Add an input to an application's input box. - /// @param _app The address of the application - /// @param _input The contents of the input + /// @param app The address of the application + /// @param input The contents of the input /// @return The hash of the input plus some extra metadata /// @dev MUST fire an `InputAdded` event accordingly. /// Input larger than machine limit will raise `InputSizeExceedsLimit` error. function addInput( - address _app, - bytes calldata _input + address app, + bytes calldata input ) external returns (bytes32); /// @notice Get the number of inputs in an application's input box. - /// @param _app The address of the application + /// @param app The address of the application /// @return Number of inputs in the application's input box - function getNumberOfInputs(address _app) external view returns (uint256); + function getNumberOfInputs(address app) external view returns (uint256); /// @notice Get the hash of an input in an application's input box. - /// @param _app The address of the application - /// @param _index The index of the input in the application's input box + /// @param app The address of the application + /// @param index The index of the input in the application's input box /// @return The hash of the input at the provided index in the application's input box - /// @dev `_index` MUST be in the interval `[0,n)` where `n` is the number of + /// @dev `index` MUST be in the interval `[0,n)` where `n` is the number of /// inputs in the application's input box. See the `getNumberOfInputs` function. function getInputHash( - address _app, - uint256 _index + address app, + uint256 index ) external view returns (bytes32); } diff --git a/onchain/rollups/contracts/inputs/InputBox.sol b/onchain/rollups/contracts/inputs/InputBox.sol index 8dac17dc..a243e79c 100644 --- a/onchain/rollups/contracts/inputs/InputBox.sol +++ b/onchain/rollups/contracts/inputs/InputBox.sol @@ -25,20 +25,20 @@ import {LibInput} from "../library/LibInput.sol"; contract InputBox is IInputBox { /// @notice Mapping from application address to list of input hashes. /// @dev See the `getNumberOfInputs`, `getInputHash` and `addInput` functions. - mapping(address => bytes32[]) internal inputBoxes; + mapping(address => bytes32[]) internal _inputBoxes; function addInput( - address _app, - bytes calldata _input + address app, + bytes calldata input ) external override returns (bytes32) { - bytes32[] storage inputBox = inputBoxes[_app]; + bytes32[] storage inputBox = _inputBoxes[app]; uint256 inputIndex = inputBox.length; bytes32 inputHash = LibInput.computeInputHash( msg.sender, block.number, block.timestamp, - _input, + input, inputIndex ); @@ -46,21 +46,21 @@ contract InputBox is IInputBox { inputBox.push(inputHash); // block.number and timestamp can be retrieved by the event metadata itself - emit InputAdded(_app, inputIndex, msg.sender, _input); + emit InputAdded(app, inputIndex, msg.sender, input); return inputHash; } function getNumberOfInputs( - address _app + address app ) external view override returns (uint256) { - return inputBoxes[_app].length; + return _inputBoxes[app].length; } function getInputHash( - address _app, - uint256 _index + address app, + uint256 index ) external view override returns (bytes32) { - return inputBoxes[_app][_index]; + return _inputBoxes[app][index]; } } diff --git a/onchain/rollups/contracts/inputs/InputRelay.sol b/onchain/rollups/contracts/inputs/InputRelay.sol index b5002a0b..29ded9b3 100644 --- a/onchain/rollups/contracts/inputs/InputRelay.sol +++ b/onchain/rollups/contracts/inputs/InputRelay.sol @@ -11,12 +11,16 @@ import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC16 /// @notice This contract serves as a base for all the other input relays. contract InputRelay is IInputRelay, ERC165 { /// @notice The input box used by the input relay. - IInputBox internal immutable inputBox; + IInputBox internal immutable _inputBox; /// @notice Constructs the input relay. - /// @param _inputBox The input box used by the input relay - constructor(IInputBox _inputBox) { - inputBox = _inputBox; + /// @param inputBox The input box used by the input relay + constructor(IInputBox inputBox) { + _inputBox = inputBox; + } + + function getInputBox() external view override returns (IInputBox) { + return _inputBox; } function supportsInterface( @@ -26,8 +30,4 @@ contract InputRelay is IInputRelay, ERC165 { interfaceId == type(IInputRelay).interfaceId || super.supportsInterface(interfaceId); } - - function getInputBox() external view override returns (IInputBox) { - return inputBox; - } } diff --git a/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol b/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol index 505b8281..1831ca48 100644 --- a/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol +++ b/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol @@ -17,42 +17,42 @@ import {InputEncoding} from "../common/InputEncoding.sol"; /// ERC-1155 tokens to an application while informing the off-chain machine. contract ERC1155BatchPortal is IERC1155BatchPortal, InputRelay { /// @notice Constructs the portal. - /// @param _inputBox The input box used by the portal - constructor(IInputBox _inputBox) InputRelay(_inputBox) {} - - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(IERC165, InputRelay) returns (bool) { - return - interfaceId == type(IERC1155BatchPortal).interfaceId || - super.supportsInterface(interfaceId); - } + /// @param inputBox The input box used by the portal + constructor(IInputBox inputBox) InputRelay(inputBox) {} function depositBatchERC1155Token( - IERC1155 _token, - address _app, - uint256[] calldata _tokenIds, - uint256[] calldata _values, - bytes calldata _baseLayerData, - bytes calldata _execLayerData + IERC1155 token, + address app, + uint256[] calldata tokenIds, + uint256[] calldata values, + bytes calldata baseLayerData, + bytes calldata execLayerData ) external override { - _token.safeBatchTransferFrom( + token.safeBatchTransferFrom( msg.sender, - _app, - _tokenIds, - _values, - _baseLayerData + app, + tokenIds, + values, + baseLayerData ); bytes memory input = InputEncoding.encodeBatchERC1155Deposit( - _token, + token, msg.sender, - _tokenIds, - _values, - _baseLayerData, - _execLayerData + tokenIds, + values, + baseLayerData, + execLayerData ); - inputBox.addInput(_app, input); + _inputBox.addInput(app, input); + } + + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(IERC165, InputRelay) returns (bool) { + return + interfaceId == type(IERC1155BatchPortal).interfaceId || + super.supportsInterface(interfaceId); } } diff --git a/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol b/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol index 6f0f8cf3..a9f70960 100644 --- a/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol +++ b/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol @@ -17,42 +17,36 @@ import {InputEncoding} from "../common/InputEncoding.sol"; /// ERC-1155 tokens to an application while informing the off-chain machine. contract ERC1155SinglePortal is IERC1155SinglePortal, InputRelay { /// @notice Constructs the portal. - /// @param _inputBox The input box used by the portal - constructor(IInputBox _inputBox) InputRelay(_inputBox) {} - - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(IERC165, InputRelay) returns (bool) { - return - interfaceId == type(IERC1155SinglePortal).interfaceId || - super.supportsInterface(interfaceId); - } + /// @param inputBox The input box used by the portal + constructor(IInputBox inputBox) InputRelay(inputBox) {} function depositSingleERC1155Token( - IERC1155 _token, - address _app, - uint256 _tokenId, - uint256 _value, - bytes calldata _baseLayerData, - bytes calldata _execLayerData + IERC1155 token, + address app, + uint256 tokenId, + uint256 value, + bytes calldata baseLayerData, + bytes calldata execLayerData ) external override { - _token.safeTransferFrom( - msg.sender, - _app, - _tokenId, - _value, - _baseLayerData - ); + token.safeTransferFrom(msg.sender, app, tokenId, value, baseLayerData); bytes memory input = InputEncoding.encodeSingleERC1155Deposit( - _token, + token, msg.sender, - _tokenId, - _value, - _baseLayerData, - _execLayerData + tokenId, + value, + baseLayerData, + execLayerData ); - inputBox.addInput(_app, input); + _inputBox.addInput(app, input); + } + + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(IERC165, InputRelay) returns (bool) { + return + interfaceId == type(IERC1155SinglePortal).interfaceId || + super.supportsInterface(interfaceId); } } diff --git a/onchain/rollups/contracts/portals/ERC20Portal.sol b/onchain/rollups/contracts/portals/ERC20Portal.sol index 92f2f04d..eb3fe154 100644 --- a/onchain/rollups/contracts/portals/ERC20Portal.sol +++ b/onchain/rollups/contracts/portals/ERC20Portal.sol @@ -20,32 +20,32 @@ contract ERC20Portal is IERC20Portal, InputRelay { using SafeERC20 for IERC20; /// @notice Constructs the portal. - /// @param _inputBox The input box used by the portal - constructor(IInputBox _inputBox) InputRelay(_inputBox) {} - - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(IERC165, InputRelay) returns (bool) { - return - interfaceId == type(IERC20Portal).interfaceId || - super.supportsInterface(interfaceId); - } + /// @param inputBox The input box used by the portal + constructor(IInputBox inputBox) InputRelay(inputBox) {} function depositERC20Tokens( - IERC20 _token, - address _app, - uint256 _amount, - bytes calldata _execLayerData + IERC20 token, + address app, + uint256 amount, + bytes calldata execLayerData ) external override { - _token.safeTransferFrom(msg.sender, _app, _amount); + token.safeTransferFrom(msg.sender, app, amount); bytes memory input = InputEncoding.encodeERC20Deposit( - _token, + token, msg.sender, - _amount, - _execLayerData + amount, + execLayerData ); - inputBox.addInput(_app, input); + _inputBox.addInput(app, input); + } + + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(IERC165, InputRelay) returns (bool) { + return + interfaceId == type(IERC20Portal).interfaceId || + super.supportsInterface(interfaceId); } } diff --git a/onchain/rollups/contracts/portals/ERC721Portal.sol b/onchain/rollups/contracts/portals/ERC721Portal.sol index 125f5a2b..5de5acd6 100644 --- a/onchain/rollups/contracts/portals/ERC721Portal.sol +++ b/onchain/rollups/contracts/portals/ERC721Portal.sol @@ -17,34 +17,34 @@ import {InputEncoding} from "../common/InputEncoding.sol"; /// ERC-721 tokens to an application while informing the off-chain machine. contract ERC721Portal is IERC721Portal, InputRelay { /// @notice Constructs the portal. - /// @param _inputBox The input box used by the portal - constructor(IInputBox _inputBox) InputRelay(_inputBox) {} - - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(IERC165, InputRelay) returns (bool) { - return - interfaceId == type(IERC721Portal).interfaceId || - super.supportsInterface(interfaceId); - } + /// @param inputBox The input box used by the portal + constructor(IInputBox inputBox) InputRelay(inputBox) {} function depositERC721Token( - IERC721 _token, - address _app, - uint256 _tokenId, - bytes calldata _baseLayerData, - bytes calldata _execLayerData + IERC721 token, + address app, + uint256 tokenId, + bytes calldata baseLayerData, + bytes calldata execLayerData ) external override { - _token.safeTransferFrom(msg.sender, _app, _tokenId, _baseLayerData); + token.safeTransferFrom(msg.sender, app, tokenId, baseLayerData); bytes memory input = InputEncoding.encodeERC721Deposit( - _token, + token, msg.sender, - _tokenId, - _baseLayerData, - _execLayerData + tokenId, + baseLayerData, + execLayerData ); - inputBox.addInput(_app, input); + _inputBox.addInput(app, input); + } + + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(IERC165, InputRelay) returns (bool) { + return + interfaceId == type(IERC721Portal).interfaceId || + super.supportsInterface(interfaceId); } } diff --git a/onchain/rollups/contracts/portals/EtherPortal.sol b/onchain/rollups/contracts/portals/EtherPortal.sol index ab96eab2..295b5bc3 100644 --- a/onchain/rollups/contracts/portals/EtherPortal.sol +++ b/onchain/rollups/contracts/portals/EtherPortal.sol @@ -19,29 +19,29 @@ contract EtherPortal is IEtherPortal, InputRelay { using Address for address payable; /// @notice Constructs the portal. - /// @param _inputBox The input box used by the portal - constructor(IInputBox _inputBox) InputRelay(_inputBox) {} - - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(IERC165, InputRelay) returns (bool) { - return - interfaceId == type(IEtherPortal).interfaceId || - super.supportsInterface(interfaceId); - } + /// @param inputBox The input box used by the portal + constructor(IInputBox inputBox) InputRelay(inputBox) {} function depositEther( - address payable _app, - bytes calldata _execLayerData + address payable app, + bytes calldata execLayerData ) external payable override { - _app.sendValue(msg.value); + app.sendValue(msg.value); bytes memory input = InputEncoding.encodeEtherDeposit( msg.sender, msg.value, - _execLayerData + execLayerData ); - inputBox.addInput(_app, input); + _inputBox.addInput(app, input); + } + + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(IERC165, InputRelay) returns (bool) { + return + interfaceId == type(IEtherPortal).interfaceId || + super.supportsInterface(interfaceId); } } diff --git a/onchain/rollups/contracts/portals/IERC1155BatchPortal.sol b/onchain/rollups/contracts/portals/IERC1155BatchPortal.sol index b1207816..abfdd66e 100644 --- a/onchain/rollups/contracts/portals/IERC1155BatchPortal.sol +++ b/onchain/rollups/contracts/portals/IERC1155BatchPortal.sol @@ -16,20 +16,20 @@ interface IERC1155BatchPortal is IInputRelay { /// The caller must enable approval for the portal to manage all of their tokens /// beforehand, by calling the `setApprovalForAll` function in the token contract. /// - /// @param _token The ERC-1155 token contract - /// @param _app The address of the application - /// @param _tokenIds The identifiers of the tokens being transferred - /// @param _values Transfer amounts per token type - /// @param _baseLayerData Additional data to be interpreted by the base layer - /// @param _execLayerData Additional data to be interpreted by the execution layer + /// @param token The ERC-1155 token contract + /// @param app The address of the application + /// @param tokenIds The identifiers of the tokens being transferred + /// @param values Transfer amounts per token type + /// @param baseLayerData Additional data to be interpreted by the base layer + /// @param execLayerData Additional data to be interpreted by the execution layer /// - /// @dev Please make sure `_tokenIds` and `_values` have the same length. + /// @dev Please make sure `tokenIds` and `values` have the same length. function depositBatchERC1155Token( - IERC1155 _token, - address _app, - uint256[] calldata _tokenIds, - uint256[] calldata _values, - bytes calldata _baseLayerData, - bytes calldata _execLayerData + IERC1155 token, + address app, + uint256[] calldata tokenIds, + uint256[] calldata values, + bytes calldata baseLayerData, + bytes calldata execLayerData ) external; } diff --git a/onchain/rollups/contracts/portals/IERC1155SinglePortal.sol b/onchain/rollups/contracts/portals/IERC1155SinglePortal.sol index 57d6efa9..2f2b5183 100644 --- a/onchain/rollups/contracts/portals/IERC1155SinglePortal.sol +++ b/onchain/rollups/contracts/portals/IERC1155SinglePortal.sol @@ -16,18 +16,18 @@ interface IERC1155SinglePortal is IInputRelay { /// The caller must enable approval for the portal to manage all of their tokens /// beforehand, by calling the `setApprovalForAll` function in the token contract. /// - /// @param _token The ERC-1155 token contract - /// @param _app The address of the application - /// @param _tokenId The identifier of the token being transferred - /// @param _value Transfer amount - /// @param _baseLayerData Additional data to be interpreted by the base layer - /// @param _execLayerData Additional data to be interpreted by the execution layer + /// @param token The ERC-1155 token contract + /// @param app The address of the application + /// @param tokenId The identifier of the token being transferred + /// @param value Transfer amount + /// @param baseLayerData Additional data to be interpreted by the base layer + /// @param execLayerData Additional data to be interpreted by the execution layer function depositSingleERC1155Token( - IERC1155 _token, - address _app, - uint256 _tokenId, - uint256 _value, - bytes calldata _baseLayerData, - bytes calldata _execLayerData + IERC1155 token, + address app, + uint256 tokenId, + uint256 value, + bytes calldata baseLayerData, + bytes calldata execLayerData ) external; } diff --git a/onchain/rollups/contracts/portals/IERC20Portal.sol b/onchain/rollups/contracts/portals/IERC20Portal.sol index a39cd8f7..7408fd2d 100644 --- a/onchain/rollups/contracts/portals/IERC20Portal.sol +++ b/onchain/rollups/contracts/portals/IERC20Portal.sol @@ -13,18 +13,18 @@ interface IERC20Portal is IInputRelay { /// @notice Transfer ERC-20 tokens to an application and add an input to /// the application's input box to signal such operation. /// - /// The caller must allow the portal to withdraw at least `_amount` tokens + /// The caller must allow the portal to withdraw at least `amount` tokens /// from their account beforehand, by calling the `approve` function in the /// token contract. /// - /// @param _token The ERC-20 token contract - /// @param _app The address of the application - /// @param _amount The amount of tokens to be transferred - /// @param _execLayerData Additional data to be interpreted by the execution layer + /// @param token The ERC-20 token contract + /// @param app The address of the application + /// @param amount The amount of tokens to be transferred + /// @param execLayerData Additional data to be interpreted by the execution layer function depositERC20Tokens( - IERC20 _token, - address _app, - uint256 _amount, - bytes calldata _execLayerData + IERC20 token, + address app, + uint256 amount, + bytes calldata execLayerData ) external; } diff --git a/onchain/rollups/contracts/portals/IERC721Portal.sol b/onchain/rollups/contracts/portals/IERC721Portal.sol index eae8e01e..8e3cd384 100644 --- a/onchain/rollups/contracts/portals/IERC721Portal.sol +++ b/onchain/rollups/contracts/portals/IERC721Portal.sol @@ -17,16 +17,16 @@ interface IERC721Portal is IInputRelay { /// to the portal address beforehand, by calling the `approve` function in the /// token contract. /// - /// @param _token The ERC-721 token contract - /// @param _app The address of the application - /// @param _tokenId The identifier of the token being transferred - /// @param _baseLayerData Additional data to be interpreted by the base layer - /// @param _execLayerData Additional data to be interpreted by the execution layer + /// @param token The ERC-721 token contract + /// @param app The address of the application + /// @param tokenId The identifier of the token being transferred + /// @param baseLayerData Additional data to be interpreted by the base layer + /// @param execLayerData Additional data to be interpreted by the execution layer function depositERC721Token( - IERC721 _token, - address _app, - uint256 _tokenId, - bytes calldata _baseLayerData, - bytes calldata _execLayerData + IERC721 token, + address app, + uint256 tokenId, + bytes calldata baseLayerData, + bytes calldata execLayerData ) external; } diff --git a/onchain/rollups/contracts/portals/IEtherPortal.sol b/onchain/rollups/contracts/portals/IEtherPortal.sol index e7e74a9d..66d4e766 100644 --- a/onchain/rollups/contracts/portals/IEtherPortal.sol +++ b/onchain/rollups/contracts/portals/IEtherPortal.sol @@ -14,12 +14,12 @@ interface IEtherPortal is IInputRelay { /// /// All the value sent through this function is forwarded to the application. /// - /// @param _app The address of the application - /// @param _execLayerData Additional data to be interpreted by the execution layer + /// @param app The address of the application + /// @param execLayerData Additional data to be interpreted by the execution layer /// @dev All the value sent through this function is forwarded to the application. /// If the transfer fails, `EtherTransferFailed` error is raised. function depositEther( - address payable _app, - bytes calldata _execLayerData + address payable app, + bytes calldata execLayerData ) external payable; } diff --git a/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol b/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol index 7ed8f223..1cd044fa 100644 --- a/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol +++ b/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol @@ -16,8 +16,13 @@ import {InputEncoding} from "../common/InputEncoding.sol"; /// of the address of the application contract in a trustless and permissionless way. contract ApplicationAddressRelay is IApplicationAddressRelay, InputRelay { /// @notice Constructs the relay. - /// @param _inputBox The input box used by the relay - constructor(IInputBox _inputBox) InputRelay(_inputBox) {} + /// @param inputBox The input box used by the relay + constructor(IInputBox inputBox) InputRelay(inputBox) {} + + function relayApplicationAddress(address app) external override { + bytes memory input = InputEncoding.encodeApplicationAddressRelay(app); + _inputBox.addInput(app, input); + } function supportsInterface( bytes4 interfaceId @@ -26,9 +31,4 @@ contract ApplicationAddressRelay is IApplicationAddressRelay, InputRelay { interfaceId == type(IApplicationAddressRelay).interfaceId || super.supportsInterface(interfaceId); } - - function relayApplicationAddress(address _app) external override { - bytes memory input = InputEncoding.encodeApplicationAddressRelay(_app); - inputBox.addInput(_app, input); - } } diff --git a/onchain/rollups/contracts/relays/IApplicationAddressRelay.sol b/onchain/rollups/contracts/relays/IApplicationAddressRelay.sol index f1483f2f..45796a50 100644 --- a/onchain/rollups/contracts/relays/IApplicationAddressRelay.sol +++ b/onchain/rollups/contracts/relays/IApplicationAddressRelay.sol @@ -10,6 +10,6 @@ interface IApplicationAddressRelay is IInputRelay { // Permissionless functions /// @notice Add an input to an application's input box with its address. - /// @param _app The address of the application - function relayApplicationAddress(address _app) external; + /// @param app The address of the application + function relayApplicationAddress(address app) external; } diff --git a/onchain/rollups/test/foundry/consensus/authority/Authority.t.sol b/onchain/rollups/test/foundry/consensus/authority/Authority.t.sol index a9224c6f..282e6d9b 100644 --- a/onchain/rollups/test/foundry/consensus/authority/Authority.t.sol +++ b/onchain/rollups/test/foundry/consensus/authority/Authority.t.sol @@ -80,7 +80,7 @@ contract AuthorityTest is TestBase { // First claim - expectClaimEvents(authority, owner, app, inputRange, epochHash1); + _expectClaimEvents(authority, owner, app, inputRange, epochHash1); vm.prank(owner); authority.submitClaim(app, inputRange, epochHash1); @@ -89,7 +89,7 @@ contract AuthorityTest is TestBase { // Second claim - expectClaimEvents(authority, owner, app, inputRange, epochHash2); + _expectClaimEvents(authority, owner, app, inputRange, epochHash2); vm.prank(owner); authority.submitClaim(app, inputRange, epochHash2); @@ -97,7 +97,7 @@ contract AuthorityTest is TestBase { assertEq(authority.getEpochHash(app, inputRange), epochHash2); } - function expectClaimEvents( + function _expectClaimEvents( Authority authority, address owner, address app, diff --git a/onchain/rollups/test/foundry/consensus/authority/AuthorityFactory.t.sol b/onchain/rollups/test/foundry/consensus/authority/AuthorityFactory.t.sol index 963b76a4..cddf1e13 100644 --- a/onchain/rollups/test/foundry/consensus/authority/AuthorityFactory.t.sol +++ b/onchain/rollups/test/foundry/consensus/authority/AuthorityFactory.t.sol @@ -10,7 +10,7 @@ import {Authority} from "contracts/consensus/authority/Authority.sol"; import {Vm} from "forge-std/Vm.sol"; contract AuthorityFactoryTest is Test { - AuthorityFactory factory; + AuthorityFactory _factory; struct AuthorityCreatedEventData { address authorityOwner; @@ -18,22 +18,55 @@ contract AuthorityFactoryTest is Test { } function setUp() public { - factory = new AuthorityFactory(); + _factory = new AuthorityFactory(); } - function testNewAuthority(address _authorityOwner) public { - vm.assume(_authorityOwner != address(0)); + function testNewAuthority(address authorityOwner) public { + vm.assume(authorityOwner != address(0)); vm.recordLogs(); - Authority authority = factory.newAuthority(_authorityOwner); + Authority authority = _factory.newAuthority(authorityOwner); - testNewAuthorityAux(_authorityOwner, authority); + _testNewAuthorityAux(authorityOwner, authority); } - function testNewAuthorityAux( - address _authorityOwner, - Authority _authority + function testNewAuthorityDeterministic( + address authorityOwner, + bytes32 salt + ) public { + vm.assume(authorityOwner != address(0)); + + address precalculatedAddress = _factory.calculateAuthorityAddress( + authorityOwner, + salt + ); + + vm.recordLogs(); + + Authority authority = _factory.newAuthority(authorityOwner, salt); + + _testNewAuthorityAux(authorityOwner, authority); + + // Precalculated address must match actual address + assertEq(precalculatedAddress, address(authority)); + + precalculatedAddress = _factory.calculateAuthorityAddress( + authorityOwner, + salt + ); + + // Precalculated address must STILL match actual address + assertEq(precalculatedAddress, address(authority)); + + // Cannot deploy an authority with the same salt twice + vm.expectRevert(); + _factory.newAuthority(authorityOwner, salt); + } + + function _testNewAuthorityAux( + address authorityOwner, + Authority authority ) internal { Vm.Log[] memory entries = vm.getRecordedLogs(); @@ -43,7 +76,7 @@ contract AuthorityFactoryTest is Test { Vm.Log memory entry = entries[i]; if ( - entry.emitter == address(factory) && + entry.emitter == address(_factory) && entry.topics[0] == IAuthorityFactory.AuthorityCreated.selector ) { ++numOfAuthorityCreated; @@ -52,47 +85,14 @@ contract AuthorityFactoryTest is Test { eventData = abi.decode(entry.data, (AuthorityCreatedEventData)); - assertEq(_authorityOwner, eventData.authorityOwner); - assertEq(address(_authority), address(eventData.authority)); + assertEq(authorityOwner, eventData.authorityOwner); + assertEq(address(authority), address(eventData.authority)); } } assertEq(numOfAuthorityCreated, 1); // call to check authority's owner - assertEq(_authority.owner(), _authorityOwner); - } - - function testNewAuthorityDeterministic( - address _authorityOwner, - bytes32 _salt - ) public { - vm.assume(_authorityOwner != address(0)); - - address precalculatedAddress = factory.calculateAuthorityAddress( - _authorityOwner, - _salt - ); - - vm.recordLogs(); - - Authority authority = factory.newAuthority(_authorityOwner, _salt); - - testNewAuthorityAux(_authorityOwner, authority); - - // Precalculated address must match actual address - assertEq(precalculatedAddress, address(authority)); - - precalculatedAddress = factory.calculateAuthorityAddress( - _authorityOwner, - _salt - ); - - // Precalculated address must STILL match actual address - assertEq(precalculatedAddress, address(authority)); - - // Cannot deploy an authority with the same salt twice - vm.expectRevert(); - factory.newAuthority(_authorityOwner, _salt); + assertEq(authority.owner(), authorityOwner); } } diff --git a/onchain/rollups/test/foundry/dapp/Application.t.sol b/onchain/rollups/test/foundry/dapp/Application.t.sol index f4e5a6a8..e6b57009 100644 --- a/onchain/rollups/test/foundry/dapp/Application.t.sol +++ b/onchain/rollups/test/foundry/dapp/Application.t.sol @@ -51,6 +51,31 @@ contract ApplicationTest is TestBase { ERC721TransferVoucher } + struct Voucher { + address destination; + bytes payload; + } + + Application _app; + IConsensus _consensus; + IERC20 _erc20Token; + IERC721 _erc721Token; + IInputRelay[] _inputRelays; + LibServerManager.OutputEnum[] _outputEnums; + mapping(uint256 => Voucher) _vouchers; + mapping(uint256 => bytes) _notices; + bytes _encodedFinishEpochResponse; + IInputBox immutable _inputBox; + address immutable _appOwner; + address immutable _noticeSender; + address immutable _recipient; + address immutable _tokenOwner; + bytes32 immutable _salt; + bytes32 immutable _templateHash; + uint256 immutable _initialSupply; + uint256 immutable _tokenId; + uint256 immutable _transferAmount; + error UnexpectedOutputEnum( LibServerManager.OutputEnum expected, LibServerManager.OutputEnum obtained, @@ -67,49 +92,21 @@ contract ApplicationTest is TestBase { uint256 inputIndexWithinEpoch ); - Application app; - IConsensus consensus; - IERC20 erc20Token; - IERC721 erc721Token; - - struct Voucher { - address destination; - bytes payload; - } - - LibServerManager.OutputEnum[] outputEnums; - mapping(uint256 => Voucher) vouchers; - mapping(uint256 => bytes) notices; - - bytes encodedFinishEpochResponse; - - IInputBox immutable inputBox; - address immutable appOwner; - address immutable noticeSender; - address immutable recipient; - address immutable tokenOwner; - bytes32 immutable salt; - bytes32 immutable templateHash; - uint256 immutable initialSupply; - uint256 immutable tokenId; - uint256 immutable transferAmount; - IInputRelay[] inputRelays; - constructor() { - appOwner = LibBytes.hashToAddress("appOwner"); - initialSupply = LibBytes.hashToUint256("initialSupply"); - inputBox = IInputBox(LibBytes.hashToAddress("inputBox")); - noticeSender = LibBytes.hashToAddress("noticeSender"); - recipient = LibBytes.hashToAddress("recipient"); - salt = keccak256("salt"); - templateHash = keccak256("templateHash"); - tokenId = LibBytes.hashToUint256("tokenId"); - tokenOwner = LibBytes.hashToAddress("tokenOwner"); - transferAmount = + _appOwner = LibBytes.hashToAddress("appOwner"); + _initialSupply = LibBytes.hashToUint256("initialSupply"); + _inputBox = IInputBox(LibBytes.hashToAddress("inputBox")); + _noticeSender = LibBytes.hashToAddress("noticeSender"); + _recipient = LibBytes.hashToAddress("recipient"); + _salt = keccak256("salt"); + _templateHash = keccak256("templateHash"); + _tokenId = LibBytes.hashToUint256("tokenId"); + _tokenOwner = LibBytes.hashToAddress("tokenOwner"); + _transferAmount = LibBytes.hashToUint256("transferAmount") % - (initialSupply + 1); + (_initialSupply + 1); for (uint256 i; i < 5; ++i) { - inputRelays.push( + _inputRelays.push( IInputRelay( LibBytes.hashToAddress(abi.encode("Input Relays", i)) ) @@ -118,32 +115,32 @@ contract ApplicationTest is TestBase { } function setUp() public { - deployContracts(); - generateOutputs(); - writeInputs(); - removeExtraInputs(); - readFinishEpochResponse(); + _deployContracts(); + _generateOutputs(); + _writeInputs(); + _removeExtraInputs(); + _readFinishEpochResponse(); } - function testSupportsInterface(bytes4 _randomInterfaceId) public { - assertTrue(app.supportsInterface(type(IApplication).interfaceId)); - assertTrue(app.supportsInterface(type(IERC721Receiver).interfaceId)); - assertTrue(app.supportsInterface(type(IERC1155Receiver).interfaceId)); - assertTrue(app.supportsInterface(type(IERC165).interfaceId)); + function testSupportsInterface(bytes4 randomInterfaceId) public { + assertTrue(_app.supportsInterface(type(IApplication).interfaceId)); + assertTrue(_app.supportsInterface(type(IERC721Receiver).interfaceId)); + assertTrue(_app.supportsInterface(type(IERC1155Receiver).interfaceId)); + assertTrue(_app.supportsInterface(type(IERC165).interfaceId)); - assertFalse(app.supportsInterface(bytes4(0xffffffff))); + assertFalse(_app.supportsInterface(bytes4(0xffffffff))); - vm.assume(_randomInterfaceId != type(IApplication).interfaceId); - vm.assume(_randomInterfaceId != type(IERC721Receiver).interfaceId); - vm.assume(_randomInterfaceId != type(IERC1155Receiver).interfaceId); - vm.assume(_randomInterfaceId != type(IERC165).interfaceId); - assertFalse(app.supportsInterface(_randomInterfaceId)); + vm.assume(randomInterfaceId != type(IApplication).interfaceId); + vm.assume(randomInterfaceId != type(IERC721Receiver).interfaceId); + vm.assume(randomInterfaceId != type(IERC1155Receiver).interfaceId); + vm.assume(randomInterfaceId != type(IERC165).interfaceId); + assertFalse(_app.supportsInterface(randomInterfaceId)); } function testConstructorWithOwnerAsZeroAddress( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - bytes32 _templateHash + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + bytes32 templateHash ) public { vm.expectRevert( abi.encodeWithSelector( @@ -152,139 +149,145 @@ contract ApplicationTest is TestBase { ) ); new Application( - consensus, - _inputBox, - _inputRelays, + _consensus, + inputBox, + inputRelays, address(0), - _templateHash + templateHash ); } function testConstructor( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _owner, - bytes32 _templateHash + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address owner, + bytes32 templateHash ) public { - vm.assume(_owner != address(0)); + vm.assume(owner != address(0)); vm.expectEmit(true, true, false, false); - emit Ownable.OwnershipTransferred(address(0), _owner); + emit Ownable.OwnershipTransferred(address(0), owner); - app = new Application( - consensus, - _inputBox, - _inputRelays, - _owner, - _templateHash + _app = new Application( + _consensus, + inputBox, + inputRelays, + owner, + templateHash ); - assertEq(address(app.getConsensus()), address(consensus)); - assertEq(address(app.getInputBox()), address(_inputBox)); + assertEq(address(_app.getConsensus()), address(_consensus)); + assertEq(address(_app.getInputBox()), address(inputBox)); // abi.encode is used instead of a loop - assertEq(abi.encode(app.getInputRelays()), abi.encode(_inputRelays)); - assertEq(app.owner(), _owner); - assertEq(app.getTemplateHash(), _templateHash); + assertEq(abi.encode(_app.getInputRelays()), abi.encode(inputRelays)); + assertEq(_app.owner(), owner); + assertEq(_app.getTemplateHash(), templateHash); } // test notices function testNoticeValidation() public { - bytes memory notice = getNotice(OutputName.DummyNotice); - Proof memory proof = setupNoticeProof(OutputName.DummyNotice); + bytes memory notice = _getNotice(OutputName.DummyNotice); + Proof memory proof = _setupNoticeProof(OutputName.DummyNotice); - validateNotice(notice, proof); + _validateNotice(notice, proof); // reverts if notice is incorrect bytes memory falseNotice = abi.encodePacked(bytes4(0xdeaddead)); vm.expectRevert( LibOutputValidation.IncorrectOutputHashesRootHash.selector ); - validateNotice(falseNotice, proof); + _validateNotice(falseNotice, proof); } // test vouchers - function testExecuteVoucherAndEvent(uint256 _appInitBalance) public { - _appInitBalance = boundBalance(_appInitBalance); + function testExecuteVoucherAndEvent(uint256 appInitBalance) public { + appInitBalance = _boundBalance(appInitBalance); - Voucher memory voucher = getVoucher(OutputName.ERC20TransferVoucher); - Proof memory proof = setupVoucherProof(OutputName.ERC20TransferVoucher); + Voucher memory voucher = _getVoucher(OutputName.ERC20TransferVoucher); + Proof memory proof = _setupVoucherProof( + OutputName.ERC20TransferVoucher + ); // not able to execute voucher because application has 0 balance - assertEq(erc20Token.balanceOf(address(app)), 0); - assertEq(erc20Token.balanceOf(recipient), 0); + assertEq(_erc20Token.balanceOf(address(_app)), 0); + assertEq(_erc20Token.balanceOf(_recipient), 0); vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientBalance.selector, - address(app), + address(_app), 0, - transferAmount + _transferAmount ) ); - executeVoucher(voucher, proof); - assertEq(erc20Token.balanceOf(address(app)), 0); - assertEq(erc20Token.balanceOf(recipient), 0); + _executeVoucher(voucher, proof); + assertEq(_erc20Token.balanceOf(address(_app)), 0); + assertEq(_erc20Token.balanceOf(_recipient), 0); // fund application - vm.prank(tokenOwner); - erc20Token.transfer(address(app), _appInitBalance); - assertEq(erc20Token.balanceOf(address(app)), _appInitBalance); - assertEq(erc20Token.balanceOf(recipient), 0); + vm.prank(_tokenOwner); + _erc20Token.transfer(address(_app), appInitBalance); + assertEq(_erc20Token.balanceOf(address(_app)), appInitBalance); + assertEq(_erc20Token.balanceOf(_recipient), 0); // expect event - vm.expectEmit(false, false, false, true, address(app)); + vm.expectEmit(false, false, false, true, address(_app)); emit IApplication.VoucherExecuted( _calculateInputIndex(proof), proof.validity.outputIndexWithinInput ); // perform call - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); // check result assertEq( - erc20Token.balanceOf(address(app)), - _appInitBalance - transferAmount + _erc20Token.balanceOf(address(_app)), + appInitBalance - _transferAmount ); - assertEq(erc20Token.balanceOf(recipient), transferAmount); + assertEq(_erc20Token.balanceOf(_recipient), _transferAmount); } - function testRevertsReexecution(uint256 _appInitBalance) public { - _appInitBalance = boundBalance(_appInitBalance); + function testRevertsReexecution(uint256 appInitBalance) public { + appInitBalance = _boundBalance(appInitBalance); - Voucher memory voucher = getVoucher(OutputName.ERC20TransferVoucher); - Proof memory proof = setupVoucherProof(OutputName.ERC20TransferVoucher); + Voucher memory voucher = _getVoucher(OutputName.ERC20TransferVoucher); + Proof memory proof = _setupVoucherProof( + OutputName.ERC20TransferVoucher + ); // fund application - vm.prank(tokenOwner); - erc20Token.transfer(address(app), _appInitBalance); + vm.prank(_tokenOwner); + _erc20Token.transfer(address(_app), appInitBalance); // 1st execution attempt should succeed - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); // 2nd execution attempt should fail vm.expectRevert(Application.VoucherReexecutionNotAllowed.selector); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); // end result should be the same as executing successfully only once assertEq( - erc20Token.balanceOf(address(app)), - _appInitBalance - transferAmount + _erc20Token.balanceOf(address(_app)), + appInitBalance - _transferAmount ); - assertEq(erc20Token.balanceOf(recipient), transferAmount); + assertEq(_erc20Token.balanceOf(_recipient), _transferAmount); } - function testWasVoucherExecuted(uint256 _appInitBalance) public { - _appInitBalance = boundBalance(_appInitBalance); + function testWasVoucherExecuted(uint256 appInitBalance) public { + appInitBalance = _boundBalance(appInitBalance); - Voucher memory voucher = getVoucher(OutputName.ERC20TransferVoucher); - Proof memory proof = setupVoucherProof(OutputName.ERC20TransferVoucher); + Voucher memory voucher = _getVoucher(OutputName.ERC20TransferVoucher); + Proof memory proof = _setupVoucherProof( + OutputName.ERC20TransferVoucher + ); uint256 inputIndex = _calculateInputIndex(proof); // before executing voucher - bool executed = app.wasVoucherExecuted( + bool executed = _app.wasVoucherExecuted( inputIndex, proof.validity.outputIndexWithinInput ); @@ -294,27 +297,27 @@ contract ApplicationTest is TestBase { vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientBalance.selector, - address(app), + address(_app), 0, - transferAmount + _transferAmount ) ); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); // `wasVoucherExecuted` should still return false - executed = app.wasVoucherExecuted( + executed = _app.wasVoucherExecuted( inputIndex, proof.validity.outputIndexWithinInput ); assertEq(executed, false); // execute voucher - succeeded - vm.prank(tokenOwner); - erc20Token.transfer(address(app), _appInitBalance); - executeVoucher(voucher, proof); + vm.prank(_tokenOwner); + _erc20Token.transfer(address(_app), appInitBalance); + _executeVoucher(voucher, proof); // after executing voucher, `wasVoucherExecuted` should return true - executed = app.wasVoucherExecuted( + executed = _app.wasVoucherExecuted( inputIndex, proof.validity.outputIndexWithinInput ); @@ -322,43 +325,49 @@ contract ApplicationTest is TestBase { } function testRevertsEpochHash() public { - Voucher memory voucher = getVoucher(OutputName.ERC20TransferVoucher); - Proof memory proof = setupVoucherProof(OutputName.ERC20TransferVoucher); + Voucher memory voucher = _getVoucher(OutputName.ERC20TransferVoucher); + Proof memory proof = _setupVoucherProof( + OutputName.ERC20TransferVoucher + ); proof.validity.vouchersEpochRootHash = bytes32(uint256(0xdeadbeef)); vm.expectRevert(LibOutputValidation.IncorrectEpochHash.selector); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); } function testRevertsOutputsEpochRootHash() public { - Voucher memory voucher = getVoucher(OutputName.ERC20TransferVoucher); - Proof memory proof = setupVoucherProof(OutputName.ERC20TransferVoucher); + Voucher memory voucher = _getVoucher(OutputName.ERC20TransferVoucher); + Proof memory proof = _setupVoucherProof( + OutputName.ERC20TransferVoucher + ); proof.validity.outputHashesRootHash = bytes32(uint256(0xdeadbeef)); vm.expectRevert( LibOutputValidation.IncorrectOutputsEpochRootHash.selector ); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); } function testRevertsOutputHashesRootHash() public { - Voucher memory voucher = getVoucher(OutputName.ERC20TransferVoucher); - Proof memory proof = setupVoucherProof(OutputName.ERC20TransferVoucher); + Voucher memory voucher = _getVoucher(OutputName.ERC20TransferVoucher); + Proof memory proof = _setupVoucherProof( + OutputName.ERC20TransferVoucher + ); proof.validity.outputIndexWithinInput = 0xdeadbeef; vm.expectRevert( LibOutputValidation.IncorrectOutputHashesRootHash.selector ); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); } function testRevertsInputIndexOutOfRange() public { OutputName outputName = OutputName.ERC20TransferVoucher; - Voucher memory voucher = getVoucher(outputName); - Proof memory proof = getVoucherProof(uint256(outputName)); + Voucher memory voucher = _getVoucher(outputName); + Proof memory proof = _getVoucherProof(uint256(outputName)); uint256 inputIndex = _calculateInputIndex(proof); // If the input index were 0, then there would be no way for the input index @@ -370,7 +379,7 @@ contract ApplicationTest is TestBase { // before the actual input (which is still provable!). // The `Application` contract, however, will not allow such proof. proof.inputRange.lastIndex = inputIndex - 1; - mockConsensus(proof); + _mockConsensus(proof); vm.expectRevert( abi.encodeWithSelector( @@ -379,86 +388,88 @@ contract ApplicationTest is TestBase { proof.inputRange ) ); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); } // test ether transfer - function testEtherTransfer(uint256 _appInitBalance) public { - _appInitBalance = boundBalance(_appInitBalance); + function testEtherTransfer(uint256 appInitBalance) public { + appInitBalance = _boundBalance(appInitBalance); - Voucher memory voucher = getVoucher(OutputName.ETHWithdrawalVoucher); - Proof memory proof = setupVoucherProof(OutputName.ETHWithdrawalVoucher); + Voucher memory voucher = _getVoucher(OutputName.ETHWithdrawalVoucher); + Proof memory proof = _setupVoucherProof( + OutputName.ETHWithdrawalVoucher + ); // not able to execute voucher because application has 0 balance - assertEq(address(app).balance, 0); - assertEq(address(recipient).balance, 0); + assertEq(address(_app).balance, 0); + assertEq(address(_recipient).balance, 0); vm.expectRevert(); - executeVoucher(voucher, proof); - assertEq(address(app).balance, 0); - assertEq(address(recipient).balance, 0); + _executeVoucher(voucher, proof); + assertEq(address(_app).balance, 0); + assertEq(address(_recipient).balance, 0); // fund application - vm.deal(address(app), _appInitBalance); - assertEq(address(app).balance, _appInitBalance); - assertEq(address(recipient).balance, 0); + vm.deal(address(_app), appInitBalance); + assertEq(address(_app).balance, appInitBalance); + assertEq(address(_recipient).balance, 0); // expect event - vm.expectEmit(false, false, false, true, address(app)); + vm.expectEmit(false, false, false, true, address(_app)); emit IApplication.VoucherExecuted( _calculateInputIndex(proof), proof.validity.outputIndexWithinInput ); // perform call - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); // check result - assertEq(address(app).balance, _appInitBalance - transferAmount); - assertEq(address(recipient).balance, transferAmount); + assertEq(address(_app).balance, appInitBalance - _transferAmount); + assertEq(address(_recipient).balance, _transferAmount); // cannot execute the same voucher again vm.expectRevert(Application.VoucherReexecutionNotAllowed.selector); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); } function testWithdrawEtherContract( - uint256 _value, - address _notApplication + uint256 value, + address notApplication ) public { - vm.assume(_value <= address(this).balance); - vm.assume(_notApplication != address(app)); + vm.assume(value <= address(this).balance); + vm.assume(notApplication != address(_app)); address receiver = address(new EtherReceiver()); // fund application - vm.deal(address(app), _value); + vm.deal(address(_app), value); // withdrawEther cannot be called by anyone vm.expectRevert(Application.OnlyApplication.selector); - vm.prank(_notApplication); - app.withdrawEther(receiver, _value); + vm.prank(notApplication); + _app.withdrawEther(receiver, value); // withdrawEther can only be called by application itself uint256 preBalance = receiver.balance; - vm.prank(address(app)); - app.withdrawEther(receiver, _value); - assertEq(receiver.balance, preBalance + _value); - assertEq(address(app).balance, 0); + vm.prank(address(_app)); + _app.withdrawEther(receiver, value); + assertEq(receiver.balance, preBalance + value); + assertEq(address(_app).balance, 0); } function testWithdrawEtherEOA( - uint256 _value, - address _notApplication, - uint256 _receiverSeed + uint256 value, + address notApplication, + uint256 receiverSeed ) public { - vm.assume(_notApplication != address(app)); - vm.assume(_value <= address(this).balance); + vm.assume(notApplication != address(_app)); + vm.assume(value <= address(this).balance); // by deriving receiver from keccak-256, we avoid // collisions with precompiled contract addresses // assume receiver is not a contract address receiver = address( - bytes20(keccak256(abi.encode(_receiverSeed))) + bytes20(keccak256(abi.encode(receiverSeed))) ); uint256 codeSize; assembly { @@ -467,99 +478,99 @@ contract ApplicationTest is TestBase { vm.assume(codeSize == 0); // fund application - vm.deal(address(app), _value); + vm.deal(address(_app), value); // withdrawEther cannot be called by anyone vm.expectRevert(Application.OnlyApplication.selector); - vm.prank(_notApplication); - app.withdrawEther(receiver, _value); + vm.prank(notApplication); + _app.withdrawEther(receiver, value); // withdrawEther can only be called by application itself uint256 preBalance = receiver.balance; - vm.prank(address(app)); - app.withdrawEther(receiver, _value); - assertEq(receiver.balance, preBalance + _value); - assertEq(address(app).balance, 0); + vm.prank(address(_app)); + _app.withdrawEther(receiver, value); + assertEq(receiver.balance, preBalance + value); + assertEq(address(_app).balance, 0); } - function testRevertsWithdrawEther(uint256 _value, uint256 _funds) public { - vm.assume(_value > _funds); + function testRevertsWithdrawEther(uint256 value, uint256 funds) public { + vm.assume(value > funds); address receiver = address(new EtherReceiver()); // Fund application - vm.deal(address(app), _funds); + vm.deal(address(_app), funds); // application is not funded or does not have enough funds - vm.prank(address(app)); + vm.prank(address(_app)); vm.expectRevert(Application.EtherTransferFailed.selector); - app.withdrawEther(receiver, _value); + _app.withdrawEther(receiver, value); } // test NFT transfer function testWithdrawNFT() public { - Voucher memory voucher = getVoucher(OutputName.ERC721TransferVoucher); - Proof memory proof = setupVoucherProof( + Voucher memory voucher = _getVoucher(OutputName.ERC721TransferVoucher); + Proof memory proof = _setupVoucherProof( OutputName.ERC721TransferVoucher ); // not able to execute voucher because application doesn't have the nft - assertEq(erc721Token.ownerOf(tokenId), tokenOwner); + assertEq(_erc721Token.ownerOf(_tokenId), _tokenOwner); vm.expectRevert( abi.encodeWithSelector( IERC721Errors.ERC721InsufficientApproval.selector, - address(app), - tokenId + address(_app), + _tokenId ) ); - executeVoucher(voucher, proof); - assertEq(erc721Token.ownerOf(tokenId), tokenOwner); + _executeVoucher(voucher, proof); + assertEq(_erc721Token.ownerOf(_tokenId), _tokenOwner); // fund application - vm.prank(tokenOwner); - erc721Token.safeTransferFrom(tokenOwner, address(app), tokenId); - assertEq(erc721Token.ownerOf(tokenId), address(app)); + vm.prank(_tokenOwner); + _erc721Token.safeTransferFrom(_tokenOwner, address(_app), _tokenId); + assertEq(_erc721Token.ownerOf(_tokenId), address(_app)); // expect event - vm.expectEmit(false, false, false, true, address(app)); + vm.expectEmit(false, false, false, true, address(_app)); emit IApplication.VoucherExecuted( _calculateInputIndex(proof), proof.validity.outputIndexWithinInput ); // perform call - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); // check result - assertEq(erc721Token.ownerOf(tokenId), recipient); + assertEq(_erc721Token.ownerOf(_tokenId), _recipient); // cannot execute the same voucher again vm.expectRevert(Application.VoucherReexecutionNotAllowed.selector); - executeVoucher(voucher, proof); + _executeVoucher(voucher, proof); } // test migration function testMigrateToConsensus( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _owner, - bytes32 _templateHash, - address _newOwner, - address _nonZeroAddress + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address owner, + bytes32 templateHash, + address newOwner, + address nonZeroAddress ) public { - vm.assume(_owner != address(0)); - vm.assume(_owner != address(this)); - vm.assume(_owner != _newOwner); - vm.assume(address(_newOwner) != address(0)); - vm.assume(_nonZeroAddress != address(0)); + vm.assume(owner != address(0)); + vm.assume(owner != address(this)); + vm.assume(owner != newOwner); + vm.assume(address(newOwner) != address(0)); + vm.assume(nonZeroAddress != address(0)); - app = new Application( - consensus, - _inputBox, - _inputRelays, - _owner, - _templateHash + _app = new Application( + _consensus, + inputBox, + inputRelays, + owner, + templateHash ); IConsensus newConsensus = new SimpleConsensus(); @@ -571,217 +582,128 @@ contract ApplicationTest is TestBase { address(this) ) ); - app.migrateToConsensus(newConsensus); + _app.migrateToConsensus(newConsensus); // now impersonate owner - vm.prank(_owner); - vm.expectEmit(false, false, false, true, address(app)); + vm.prank(owner); + vm.expectEmit(false, false, false, true, address(_app)); emit IApplication.NewConsensus(newConsensus); - app.migrateToConsensus(newConsensus); - assertEq(address(app.getConsensus()), address(newConsensus)); + _app.migrateToConsensus(newConsensus); + assertEq(address(_app.getConsensus()), address(newConsensus)); // if owner changes, then original owner no longer can migrate consensus - vm.prank(_owner); - app.transferOwnership(_newOwner); + vm.prank(owner); + _app.transferOwnership(newOwner); vm.expectRevert( abi.encodeWithSelector( Ownable.OwnableUnauthorizedAccount.selector, - _owner + owner ) ); - vm.prank(_owner); - app.migrateToConsensus(consensus); + vm.prank(owner); + _app.migrateToConsensus(_consensus); // if new owner renounce ownership (give ownership to address 0) // no one will be able to migrate consensus - vm.prank(_newOwner); - app.renounceOwnership(); + vm.prank(newOwner); + _app.renounceOwnership(); vm.expectRevert( abi.encodeWithSelector( Ownable.OwnableUnauthorizedAccount.selector, - _nonZeroAddress + nonZeroAddress ) ); - vm.prank(_nonZeroAddress); - app.migrateToConsensus(consensus); + vm.prank(nonZeroAddress); + _app.migrateToConsensus(_consensus); } - function deployContracts() internal { - consensus = deployConsensusDeterministically(); - app = deployApplicationDeterministically(); - erc20Token = deployERC20Deterministically(); - erc721Token = deployERC721Deterministically(); + function _deployContracts() internal { + _consensus = _deployConsensusDeterministically(); + _app = _deployApplicationDeterministically(); + _erc20Token = _deployERC20Deterministically(); + _erc721Token = _deployERC721Deterministically(); } - function deployApplicationDeterministically() + function _deployApplicationDeterministically() internal returns (Application) { - vm.prank(appOwner); + vm.prank(_appOwner); return - new Application{salt: salt}( - consensus, - inputBox, - inputRelays, - appOwner, - templateHash - ); - } - - function deployConsensusDeterministically() internal returns (IConsensus) { - vm.prank(appOwner); - return new SimpleConsensus{salt: salt}(); - } - - function deployERC20Deterministically() internal returns (IERC20) { - vm.prank(tokenOwner); - return new SimpleERC20{salt: salt}(tokenOwner, initialSupply); - } - - function deployERC721Deterministically() internal returns (IERC721) { - vm.prank(tokenOwner); - return new SimpleERC721{salt: salt}(tokenOwner, tokenId); - } - - function addVoucher(address destination, bytes memory payload) internal { - uint256 index = outputEnums.length; - outputEnums.push(LibServerManager.OutputEnum.VOUCHER); - vouchers[index] = Voucher(destination, payload); - } - - function checkInputIndexWithinEpoch( - uint256 inputIndexWithinEpoch - ) internal view { - uint256 length = outputEnums.length; - if (inputIndexWithinEpoch >= length) { - revert InputIndexWithinEpochOutOfBounds( - length, - inputIndexWithinEpoch - ); - } - } - - function checkOutputEnum( - uint256 inputIndexWithinEpoch, - LibServerManager.OutputEnum expected - ) internal view { - LibServerManager.OutputEnum obtained = outputEnums[ - inputIndexWithinEpoch - ]; - if (expected != obtained) { - revert UnexpectedOutputEnum( - expected, - obtained, - inputIndexWithinEpoch + new Application{salt: _salt}( + _consensus, + _inputBox, + _inputRelays, + _appOwner, + _templateHash ); - } } - function getVoucher( - uint256 inputIndexWithinEpoch - ) internal view returns (Voucher memory) { - checkInputIndexWithinEpoch(inputIndexWithinEpoch); - checkOutputEnum( - inputIndexWithinEpoch, - LibServerManager.OutputEnum.VOUCHER - ); - return vouchers[inputIndexWithinEpoch]; + function _deployConsensusDeterministically() internal returns (IConsensus) { + vm.prank(_appOwner); + return new SimpleConsensus{salt: _salt}(); } - function getVoucher( - OutputName _outputName - ) internal view returns (Voucher memory) { - return getVoucher(uint256(_outputName)); + function _deployERC20Deterministically() internal returns (IERC20) { + vm.prank(_tokenOwner); + return new SimpleERC20{salt: _salt}(_tokenOwner, _initialSupply); } - function addNotice(bytes memory notice) internal { - uint256 index = outputEnums.length; - outputEnums.push(LibServerManager.OutputEnum.NOTICE); - notices[index] = notice; + function _deployERC721Deterministically() internal returns (IERC721) { + vm.prank(_tokenOwner); + return new SimpleERC721{salt: _salt}(_tokenOwner, _tokenId); } - function getNotice( - uint256 inputIndexWithinEpoch - ) internal view returns (bytes memory) { - checkInputIndexWithinEpoch(inputIndexWithinEpoch); - checkOutputEnum( - inputIndexWithinEpoch, - LibServerManager.OutputEnum.NOTICE - ); - return notices[inputIndexWithinEpoch]; + function _addVoucher(address destination, bytes memory payload) internal { + uint256 index = _outputEnums.length; + _outputEnums.push(LibServerManager.OutputEnum.VOUCHER); + _vouchers[index] = Voucher(destination, payload); } - function getNotice( - OutputName _outputName - ) internal view returns (bytes memory) { - return getNotice(uint256(_outputName)); + function _addNotice(bytes memory notice) internal { + uint256 index = _outputEnums.length; + _outputEnums.push(LibServerManager.OutputEnum.NOTICE); + _notices[index] = notice; } - function generateOutputs() internal { - addNotice(abi.encode(bytes4(0xfafafafa))); - addVoucher( - address(erc20Token), - abi.encodeCall(IERC20.transfer, (recipient, transferAmount)) + function _generateOutputs() internal { + _addNotice(abi.encode(bytes4(0xfafafafa))); + _addVoucher( + address(_erc20Token), + abi.encodeCall(IERC20.transfer, (_recipient, _transferAmount)) ); - addVoucher( - address(app), + _addVoucher( + address(_app), abi.encodeCall( Application.withdrawEther, - (recipient, transferAmount) + (_recipient, _transferAmount) ) ); - addVoucher( - address(erc721Token), + _addVoucher( + address(_erc721Token), abi.encodeWithSignature( "safeTransferFrom(address,address,uint256)", - app, - recipient, - tokenId + _app, + _recipient, + _tokenId ) ); } - function writeInputs() internal { - for (uint256 i; i < outputEnums.length; ++i) { - LibServerManager.OutputEnum outputEnum = outputEnums[i]; + function _writeInputs() internal { + for (uint256 i; i < _outputEnums.length; ++i) { + LibServerManager.OutputEnum outputEnum = _outputEnums[i]; if (outputEnum == LibServerManager.OutputEnum.VOUCHER) { - Voucher memory voucher = getVoucher(i); - writeInput(i, voucher.destination, voucher.payload); + Voucher memory voucher = _getVoucher(i); + _writeInput(i, voucher.destination, voucher.payload); } else { - bytes memory notice = getNotice(i); - writeInput(i, noticeSender, notice); + bytes memory notice = _getNotice(i); + _writeInput(i, _noticeSender, notice); } } } - function getInputPath( - string memory inputIndexWithinEpochStr - ) internal view returns (string memory) { - string memory root = vm.projectRoot(); - return - string.concat( - root, - "/test", - "/foundry", - "/dapp", - "/helper", - "/input", - "/", - inputIndexWithinEpochStr, - ".json" - ); - } - - function getInputPath( - uint256 inputIndexWithinEpoch - ) internal view returns (string memory) { - string memory inputIndexWithinEpochStr = vm.toString( - inputIndexWithinEpoch - ); - return getInputPath(inputIndexWithinEpochStr); - } - - function writeInput( + function _writeInput( uint256 inputIndexWithinEpoch, address sender, bytes memory payload @@ -795,20 +717,20 @@ contract ApplicationTest is TestBase { ); vm.serializeAddress(objectKey, "sender", sender); string memory json = vm.serializeBytes(objectKey, "payload", payload); - string memory path = getInputPath(inputIndexWithinEpochStr); + string memory path = _getInputPath(inputIndexWithinEpochStr); vm.writeJson(json, path); } - function removeExtraInputs() internal { - uint256 inputIndexWithinEpoch = outputEnums.length; - string memory path = getInputPath(inputIndexWithinEpoch); + function _removeExtraInputs() internal { + uint256 inputIndexWithinEpoch = _outputEnums.length; + string memory path = _getInputPath(inputIndexWithinEpoch); while (vm.isFile(path)) { vm.removeFile(path); - path = getInputPath(++inputIndexWithinEpoch); + path = _getInputPath(++inputIndexWithinEpoch); } } - function readFinishEpochResponse() internal { + function _readFinishEpochResponse() internal { // Construct path to FinishEpoch response JSON string memory root = vm.projectRoot(); string memory path = string.concat( @@ -828,84 +750,173 @@ contract ApplicationTest is TestBase { string memory json = vm.readFile(path); // Parse JSON into ABI-encoded data - encodedFinishEpochResponse = vm.parseJson(json); + _encodedFinishEpochResponse = vm.parseJson(json); } - function validateNotice( - bytes memory notice, - Proof memory proof - ) internal view { - app.validateNotice(notice, proof); + function _setupNoticeProof( + OutputName outputName + ) internal returns (Proof memory) { + uint256 inputIndexWithinEpoch = uint256(outputName); + Proof memory proof = _getNoticeProof(inputIndexWithinEpoch); + _mockConsensus(proof); + return proof; + } + + function _setupVoucherProof( + OutputName outputName + ) internal returns (Proof memory) { + uint256 inputIndexWithinEpoch = uint256(outputName); + Proof memory proof = _getVoucherProof(inputIndexWithinEpoch); + _mockConsensus(proof); + return proof; } - function executeVoucher( + function _executeVoucher( Voucher memory voucher, Proof memory proof ) internal { - app.executeVoucher(voucher.destination, voucher.payload, proof); + _app.executeVoucher(voucher.destination, voucher.payload, proof); } - function calculateEpochHash( - OutputValidityProof memory _validity - ) internal pure returns (bytes32) { - return - keccak256( - abi.encodePacked( - _validity.vouchersEpochRootHash, - _validity.noticesEpochRootHash, - _validity.machineStateHash - ) + // Mock the consensus contract so that calls to `getEpochHash` return + // the epoch hash to be used to validate the proof. + function _mockConsensus(Proof memory proof) internal { + vm.mockCall( + address(_consensus), + abi.encodeCall( + IConsensus.getEpochHash, + (address(_app), proof.inputRange) + ), + abi.encode(_calculateEpochHash(proof.validity)) + ); + } + + function _checkInputIndexWithinEpoch( + uint256 inputIndexWithinEpoch + ) internal view { + uint256 length = _outputEnums.length; + if (inputIndexWithinEpoch >= length) { + revert InputIndexWithinEpochOutOfBounds( + length, + inputIndexWithinEpoch + ); + } + } + + function _checkOutputEnum( + uint256 inputIndexWithinEpoch, + LibServerManager.OutputEnum expected + ) internal view { + LibServerManager.OutputEnum obtained = _outputEnums[ + inputIndexWithinEpoch + ]; + if (expected != obtained) { + revert UnexpectedOutputEnum( + expected, + obtained, + inputIndexWithinEpoch ); + } + } + + function _getVoucher( + uint256 inputIndexWithinEpoch + ) internal view returns (Voucher memory) { + _checkInputIndexWithinEpoch(inputIndexWithinEpoch); + _checkOutputEnum( + inputIndexWithinEpoch, + LibServerManager.OutputEnum.VOUCHER + ); + return _vouchers[inputIndexWithinEpoch]; } - function setupNoticeProof( + function _getVoucher( OutputName _outputName - ) internal returns (Proof memory) { - uint256 inputIndexWithinEpoch = uint256(_outputName); - Proof memory proof = getNoticeProof(inputIndexWithinEpoch); - mockConsensus(proof); - return proof; + ) internal view returns (Voucher memory) { + return _getVoucher(uint256(_outputName)); + } + + function _getNotice( + uint256 inputIndexWithinEpoch + ) internal view returns (bytes memory) { + _checkInputIndexWithinEpoch(inputIndexWithinEpoch); + _checkOutputEnum( + inputIndexWithinEpoch, + LibServerManager.OutputEnum.NOTICE + ); + return _notices[inputIndexWithinEpoch]; } - function setupVoucherProof( + function _getNotice( OutputName _outputName - ) internal returns (Proof memory) { - uint256 inputIndexWithinEpoch = uint256(_outputName); - Proof memory proof = getVoucherProof(inputIndexWithinEpoch); - mockConsensus(proof); - return proof; + ) internal view returns (bytes memory) { + return _getNotice(uint256(_outputName)); } - function getNoticeProof( + function _getInputPath( + string memory inputIndexWithinEpochStr + ) internal view returns (string memory) { + string memory root = vm.projectRoot(); + return + string.concat( + root, + "/test", + "/foundry", + "/dapp", + "/helper", + "/input", + "/", + inputIndexWithinEpochStr, + ".json" + ); + } + + function _getInputPath( + uint256 inputIndexWithinEpoch + ) internal view returns (string memory) { + string memory inputIndexWithinEpochStr = vm.toString( + inputIndexWithinEpoch + ); + return _getInputPath(inputIndexWithinEpochStr); + } + + function _validateNotice( + bytes memory notice, + Proof memory proof + ) internal view { + _app.validateNotice(notice, proof); + } + + function _getNoticeProof( uint256 inputIndexWithinEpoch ) internal view returns (Proof memory) { return - getProof( + _getProof( LibServerManager.OutputEnum.NOTICE, inputIndexWithinEpoch, 0 ); } - function getVoucherProof( + function _getVoucherProof( uint256 inputIndexWithinEpoch ) internal view returns (Proof memory) { return - getProof( + _getProof( LibServerManager.OutputEnum.VOUCHER, inputIndexWithinEpoch, 0 ); } - function getProof( + function _getProof( LibServerManager.OutputEnum outputEnum, uint256 inputIndexWithinEpoch, uint256 outputIndex ) internal view returns (Proof memory) { // Decode ABI-encoded data into raw struct LibServerManager.RawFinishEpochResponse memory raw = abi.decode( - encodedFinishEpochResponse, + _encodedFinishEpochResponse, (LibServerManager.RawFinishEpochResponse) ); @@ -924,7 +935,7 @@ contract ApplicationTest is TestBase { if (proof.proves(outputEnum, inputIndexWithinEpoch, outputIndex)) { return Proof({ - validity: convert(proof.validity), + validity: _convert(proof.validity), inputRange: inputRange }); } @@ -934,7 +945,36 @@ contract ApplicationTest is TestBase { revert ProofNotFound(outputEnum, inputIndexWithinEpoch); } - function convert( + function _boundBalance(uint256 balance) internal view returns (uint256) { + return bound(balance, _transferAmount, _initialSupply); + } + + function calculateInputIndex( + Proof calldata proof + ) external pure returns (uint256) { + return proof.calculateInputIndex(); + } + + function _calculateInputIndex( + Proof memory proof + ) internal view returns (uint256) { + return this.calculateInputIndex(proof); + } + + function _calculateEpochHash( + OutputValidityProof memory validity + ) internal pure returns (bytes32) { + return + keccak256( + abi.encodePacked( + validity.vouchersEpochRootHash, + validity.noticesEpochRootHash, + validity.machineStateHash + ) + ); + } + + function _convert( LibServerManager.OutputValidityProof memory v ) internal pure returns (OutputValidityProof memory) { return @@ -950,33 +990,4 @@ contract ApplicationTest is TestBase { outputHashesInEpochSiblings: v.outputHashesInEpochSiblings }); } - - // Mock the consensus contract so that calls to `getEpochHash` return - // the epoch hash to be used to validate the proof. - function mockConsensus(Proof memory _proof) internal { - vm.mockCall( - address(consensus), - abi.encodeCall( - IConsensus.getEpochHash, - (address(app), _proof.inputRange) - ), - abi.encode(calculateEpochHash(_proof.validity)) - ); - } - - function boundBalance(uint256 _balance) internal view returns (uint256) { - return bound(_balance, transferAmount, initialSupply); - } - - function calculateInputIndex( - Proof calldata _proof - ) external pure returns (uint256) { - return _proof.calculateInputIndex(); - } - - function _calculateInputIndex( - Proof memory _proof - ) internal view returns (uint256) { - return this.calculateInputIndex(_proof); - } } diff --git a/onchain/rollups/test/foundry/dapp/ApplicationFactory.t.sol b/onchain/rollups/test/foundry/dapp/ApplicationFactory.t.sol index d12c0186..99183dde 100644 --- a/onchain/rollups/test/foundry/dapp/ApplicationFactory.t.sol +++ b/onchain/rollups/test/foundry/dapp/ApplicationFactory.t.sol @@ -14,81 +14,81 @@ import {IInputRelay} from "contracts/inputs/IInputRelay.sol"; import {Vm} from "forge-std/Vm.sol"; contract ApplicationFactoryTest is TestBase { - ApplicationFactory factory; - IConsensus consensus; + ApplicationFactory _factory; + IConsensus _consensus; function setUp() public { - factory = new ApplicationFactory(); - consensus = new SimpleConsensus(); + _factory = new ApplicationFactory(); + _consensus = new SimpleConsensus(); } function testNewApplication( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash ) public { - vm.assume(_appOwner != address(0)); - - Application app = factory.newApplication( - consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash + vm.assume(appOwner != address(0)); + + Application app = _factory.newApplication( + _consensus, + inputBox, + inputRelays, + appOwner, + templateHash ); - assertEq(address(app.getConsensus()), address(consensus)); - assertEq(address(app.getInputBox()), address(_inputBox)); + assertEq(address(app.getConsensus()), address(_consensus)); + assertEq(address(app.getInputBox()), address(inputBox)); // abi.encode is used instead of a loop - assertEq(abi.encode(app.getInputRelays()), abi.encode(_inputRelays)); - assertEq(app.owner(), _appOwner); - assertEq(app.getTemplateHash(), _templateHash); + assertEq(abi.encode(app.getInputRelays()), abi.encode(inputRelays)); + assertEq(app.owner(), appOwner); + assertEq(app.getTemplateHash(), templateHash); } function testNewApplicationDeterministic( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash, - bytes32 _salt + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash, + bytes32 salt ) public { - vm.assume(_appOwner != address(0)); - - address precalculatedAddress = factory.calculateApplicationAddress( - consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash, - _salt + vm.assume(appOwner != address(0)); + + address precalculatedAddress = _factory.calculateApplicationAddress( + _consensus, + inputBox, + inputRelays, + appOwner, + templateHash, + salt ); - Application app = factory.newApplication( - consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash, - _salt + Application app = _factory.newApplication( + _consensus, + inputBox, + inputRelays, + appOwner, + templateHash, + salt ); // Precalculated address must match actual address assertEq(precalculatedAddress, address(app)); - assertEq(address(app.getConsensus()), address(consensus)); - assertEq(address(app.getInputBox()), address(_inputBox)); - assertEq(abi.encode(app.getInputRelays()), abi.encode(_inputRelays)); - assertEq(app.owner(), _appOwner); - assertEq(app.getTemplateHash(), _templateHash); - - precalculatedAddress = factory.calculateApplicationAddress( - consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash, - _salt + assertEq(address(app.getConsensus()), address(_consensus)); + assertEq(address(app.getInputBox()), address(inputBox)); + assertEq(abi.encode(app.getInputRelays()), abi.encode(inputRelays)); + assertEq(app.owner(), appOwner); + assertEq(app.getTemplateHash(), templateHash); + + precalculatedAddress = _factory.calculateApplicationAddress( + _consensus, + inputBox, + inputRelays, + appOwner, + templateHash, + salt ); // Precalculated address must STILL match actual address @@ -96,78 +96,78 @@ contract ApplicationFactoryTest is TestBase { // Cannot deploy an application with the same salt twice vm.expectRevert(bytes("")); - factory.newApplication( - consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash, - _salt + _factory.newApplication( + _consensus, + inputBox, + inputRelays, + appOwner, + templateHash, + salt ); } function testApplicationCreatedEvent( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash ) public { - vm.assume(_appOwner != address(0)); + vm.assume(appOwner != address(0)); vm.recordLogs(); - Application app = factory.newApplication( - consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash + Application app = _factory.newApplication( + _consensus, + inputBox, + inputRelays, + appOwner, + templateHash ); - testApplicationCreatedEventAux( - _inputBox, - _inputRelays, - _appOwner, - _templateHash, + _testApplicationCreatedEventAux( + inputBox, + inputRelays, + appOwner, + templateHash, app ); } function testApplicationCreatedEventDeterministic( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash, - bytes32 _salt + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash, + bytes32 salt ) public { - vm.assume(_appOwner != address(0)); + vm.assume(appOwner != address(0)); vm.recordLogs(); - Application app = factory.newApplication( - consensus, - _inputBox, - _inputRelays, - _appOwner, - _templateHash, - _salt + Application app = _factory.newApplication( + _consensus, + inputBox, + inputRelays, + appOwner, + templateHash, + salt ); - testApplicationCreatedEventAux( - _inputBox, - _inputRelays, - _appOwner, - _templateHash, + _testApplicationCreatedEventAux( + inputBox, + inputRelays, + appOwner, + templateHash, app ); } - function testApplicationCreatedEventAux( - IInputBox _inputBox, - IInputRelay[] calldata _inputRelays, - address _appOwner, - bytes32 _templateHash, - Application _app + function _testApplicationCreatedEventAux( + IInputBox inputBox, + IInputRelay[] calldata inputRelays, + address appOwner, + bytes32 templateHash, + Application app ) internal { Vm.Log[] memory entries = vm.getRecordedLogs(); @@ -177,7 +177,7 @@ contract ApplicationFactoryTest is TestBase { Vm.Log memory entry = entries[i]; if ( - entry.emitter == address(factory) && + entry.emitter == address(_factory) && entry.topics[0] == IApplicationFactory.ApplicationCreated.selector ) { @@ -185,15 +185,15 @@ contract ApplicationFactoryTest is TestBase { assertEq( entry.topics[1], - bytes32(uint256(uint160(address(consensus)))) + bytes32(uint256(uint160(address(_consensus)))) ); ( - IInputBox inputBox, - IInputRelay[] memory inputRelays, - address appOwner, - bytes32 templateHash, - Application app + IInputBox inputBox_, + IInputRelay[] memory inputRelays_, + address appOwner_, + bytes32 templateHash_, + Application app_ ) = abi.decode( entry.data, ( @@ -205,11 +205,11 @@ contract ApplicationFactoryTest is TestBase { ) ); - assertEq(address(_inputBox), address(inputBox)); - assertEq(abi.encode(_inputRelays), abi.encode(inputRelays)); - assertEq(_appOwner, appOwner); - assertEq(_templateHash, templateHash); - assertEq(address(_app), address(app)); + assertEq(address(inputBox), address(inputBox_)); + assertEq(abi.encode(inputRelays), abi.encode(inputRelays_)); + assertEq(appOwner, appOwner_); + assertEq(templateHash, templateHash_); + assertEq(address(app), address(app_)); } } diff --git a/onchain/rollups/test/foundry/inputs/InputBox.t.sol b/onchain/rollups/test/foundry/inputs/InputBox.t.sol index 80c2c94e..d576627e 100644 --- a/onchain/rollups/test/foundry/inputs/InputBox.t.sol +++ b/onchain/rollups/test/foundry/inputs/InputBox.t.sol @@ -11,89 +11,86 @@ import {CanonicalMachine} from "contracts/common/CanonicalMachine.sol"; import {LibInput} from "contracts/library/LibInput.sol"; contract InputBoxHandler is Test { - IInputBox immutable inputBox; - struct InputData { address app; uint256 index; bytes32 inputHash; } - InputData[] inputDataArray; + IInputBox immutable _inputBox; + InputData[] _inputDataArray; // array of addresses of applications whose input boxes aren't empty - address[] apps; - + address[] _apps; // mapping of application addresses to number of inputs - mapping(address => uint256) numOfInputs; - + mapping(address => uint256) _numOfInputs; // block variables - uint256 blockTimestamp = block.timestamp; - uint256 blockNumber = block.number; + uint256 _blockTimestamp = block.timestamp; + uint256 _blockNumber = block.number; - constructor(IInputBox _inputBox) { - inputBox = _inputBox; + constructor(IInputBox inputBox) { + _inputBox = inputBox; } function incrementBlockTimestamp() external { - blockTimestamp++; + _blockTimestamp++; } function incrementBlockNumber() external { - blockNumber++; + _blockNumber++; } - function setBlockProperties() internal { - vm.warp(blockTimestamp); - vm.roll(blockNumber); + function _setBlockProperties() internal { + vm.warp(_blockTimestamp); + vm.roll(_blockNumber); } - function addInput(address _app, bytes calldata _input) external { + function addInput(address app, bytes calldata input) external { // For some reason, the invariant testing framework doesn't // record changes made to block properties, so we have to // set them in the beginning of every call - setBlockProperties(); + _setBlockProperties(); // Get the index of the to-be-added input - uint256 index = inputBox.getNumberOfInputs(_app); + uint256 index = _inputBox.getNumberOfInputs(app); // Check if `getNumberOfInputs` matches internal count - assertEq(index, numOfInputs[_app], "input box size"); + assertEq(index, _numOfInputs[app], "input box size"); // Make the sender add the input to the application's input box vm.prank(msg.sender); - bytes32 inputHash = inputBox.addInput(_app, _input); + bytes32 inputHash = _inputBox.addInput(app, input); // If this is the first input being added to the application's input box, // then push the application to the array of applications if (index == 0) { - apps.push(_app); + _apps.push(app); } // Increment the application's input count - ++numOfInputs[_app]; + ++_numOfInputs[app]; // Create the input data struct InputData memory inputData = InputData({ - app: _app, + app: app, index: index, inputHash: inputHash }); // Add the input data to the array - inputDataArray.push(inputData); + _inputDataArray.push(inputData); // Check if the input box size increases by one assertEq( index + 1, - inputBox.getNumberOfInputs(_app), + _inputBox.getNumberOfInputs(app), "input box size increment" ); // Check if the input hash matches the one returned by `getInputHash` assertEq( inputHash, - inputBox.getInputHash(_app, index), + _inputBox.getInputHash(app, index), "returned input hash" ); @@ -102,7 +99,7 @@ contract InputBoxHandler is Test { msg.sender, block.number, block.timestamp, - _input, + input, index ); @@ -111,64 +108,64 @@ contract InputBoxHandler is Test { } function getTotalNumberOfInputs() external view returns (uint256) { - return inputDataArray.length; + return _inputDataArray.length; } - function getInputAt(uint256 _i) external view returns (InputData memory) { - return inputDataArray[_i]; + function getInputAt(uint256 i) external view returns (InputData memory) { + return _inputDataArray[i]; } function getNumberOfApplications() external view returns (uint256) { - return apps.length; + return _apps.length; } - function getApplicationAt(uint256 _i) external view returns (address) { - return apps[_i]; + function getApplicationAt(uint256 i) external view returns (address) { + return _apps[i]; } - function getNumberOfInputs(address _app) external view returns (uint256) { - return numOfInputs[_app]; + function getNumberOfInputs(address app) external view returns (uint256) { + return _numOfInputs[app]; } } contract InputBoxTest is Test { using CanonicalMachine for CanonicalMachine.Log2Size; - InputBox inputBox; - InputBoxHandler handler; + InputBox _inputBox; + InputBoxHandler _handler; function setUp() public { - inputBox = new InputBox(); - handler = new InputBoxHandler(inputBox); + _inputBox = new InputBox(); + _handler = new InputBoxHandler(_inputBox); // for the invariant testing, // don't call the input box contract directly // (do it through the handler contract) - excludeContract(address(inputBox)); + excludeContract(address(_inputBox)); } - function testNoInputs(address _app) public { - assertEq(inputBox.getNumberOfInputs(_app), 0); + function testNoInputs(address app) public { + assertEq(_inputBox.getNumberOfInputs(app), 0); } function testAddLargeInput() public { address app = vm.addr(1); - inputBox.addInput(app, new bytes(CanonicalMachine.INPUT_MAX_SIZE)); + _inputBox.addInput(app, new bytes(CanonicalMachine.INPUT_MAX_SIZE)); vm.expectRevert(LibInput.InputSizeExceedsLimit.selector); - inputBox.addInput(app, new bytes(CanonicalMachine.INPUT_MAX_SIZE + 1)); + _inputBox.addInput(app, new bytes(CanonicalMachine.INPUT_MAX_SIZE + 1)); } // fuzz testing with multiple inputs - function testAddInput(address _app, bytes[] calldata _inputs) public { - uint256 numInputs = _inputs.length; + function testAddInput(address app, bytes[] calldata inputs) public { + uint256 numInputs = inputs.length; bytes32[] memory returnedValues = new bytes32[](numInputs); uint256 year2022 = 1641070800; // Unix Timestamp for 2022 // assume #bytes for each input is within bounds for (uint256 i; i < numInputs; ++i) { - vm.assume(_inputs[i].length <= CanonicalMachine.INPUT_MAX_SIZE); + vm.assume(inputs[i].length <= CanonicalMachine.INPUT_MAX_SIZE); } // adding inputs @@ -178,15 +175,15 @@ contract InputBoxTest is Test { vm.warp(i + year2022); // year 2022 // topics 1 and 2 are indexed; topic 3 isn't; check event data - vm.expectEmit(true, true, false, true, address(inputBox)); + vm.expectEmit(true, true, false, true, address(_inputBox)); // The event we expect - emit IInputBox.InputAdded(_app, i, address(this), _inputs[i]); + emit IInputBox.InputAdded(app, i, address(this), inputs[i]); - returnedValues[i] = inputBox.addInput(_app, _inputs[i]); + returnedValues[i] = _inputBox.addInput(app, inputs[i]); // test whether the number of inputs has increased - assertEq(i + 1, inputBox.getNumberOfInputs(_app)); + assertEq(i + 1, _inputBox.getNumberOfInputs(app)); } // testing added inputs @@ -196,11 +193,11 @@ contract InputBoxTest is Test { address(this), i, // block.number i + year2022, // block.timestamp - _inputs[i], + inputs[i], i // inputBox.length ); // test if input hash is the same as in InputBox - assertEq(inputHash, inputBox.getInputHash(_app, i)); + assertEq(inputHash, _inputBox.getInputHash(app, i)); // test if input hash is the same as returned from calling addInput() function assertEq(inputHash, returnedValues[i]); } @@ -208,21 +205,21 @@ contract InputBoxTest is Test { function invariantInputData() external { // Get the total number of inputs - uint256 totalNumOfInputs = handler.getTotalNumberOfInputs(); + uint256 totalNumOfInputs = _handler.getTotalNumberOfInputs(); for (uint256 i; i < totalNumOfInputs; ++i) { // Get input data and metadata passed to `addInput` - InputBoxHandler.InputData memory inputData = handler.getInputAt(i); + InputBoxHandler.InputData memory inputData = _handler.getInputAt(i); // Make sure the input index is less than the input box size assertLt( inputData.index, - inputBox.getNumberOfInputs(inputData.app), + _inputBox.getNumberOfInputs(inputData.app), "index bound check" ); // Get the input hash returned by `getInputHash` - bytes32 inputHash = inputBox.getInputHash( + bytes32 inputHash = _inputBox.getInputHash( inputData.app, inputData.index ); @@ -232,15 +229,15 @@ contract InputBoxTest is Test { } // Get the number of applications in the array - uint256 numOfApplications = handler.getNumberOfApplications(); + uint256 numOfApplications = _handler.getNumberOfApplications(); // Check the input box size of all the applications that // were interacted with, and sum them all up uint256 sum; for (uint256 i; i < numOfApplications; ++i) { - address app = handler.getApplicationAt(i); - uint256 expected = handler.getNumberOfInputs(app); - uint256 actual = inputBox.getNumberOfInputs(app); + address app = _handler.getApplicationAt(i); + uint256 expected = _handler.getNumberOfInputs(app); + uint256 actual = _inputBox.getNumberOfInputs(app); assertEq(expected, actual, "number of inputs for app"); sum += actual; } diff --git a/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol b/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol index 0ae394cf..42e9b94b 100644 --- a/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol +++ b/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol @@ -171,25 +171,6 @@ contract ERC20PortalTest is Test { assertEq(token.balanceOf(address(_portal)), 0); } - function _encodeInput( - uint256 amount, - bytes calldata data - ) internal view returns (bytes memory) { - return InputEncoding.encodeERC20Deposit(_token, _alice, amount, data); - } - - function _encodeTransferFrom( - uint256 amount - ) internal view returns (bytes memory) { - return abi.encodeCall(IERC20.transferFrom, (_alice, _app, amount)); - } - - function _encodeAddInput( - bytes memory _input - ) internal view returns (bytes memory) { - return abi.encodeCall(IInputBox.addInput, (_app, _input)); - } - function _testTokenReturns( uint256 amount, bytes calldata data, @@ -212,4 +193,23 @@ contract ERC20PortalTest is Test { vm.prank(_alice); _portal.depositERC20Tokens(_token, _app, amount, data); } + + function _encodeInput( + uint256 amount, + bytes calldata data + ) internal view returns (bytes memory) { + return InputEncoding.encodeERC20Deposit(_token, _alice, amount, data); + } + + function _encodeTransferFrom( + uint256 amount + ) internal view returns (bytes memory) { + return abi.encodeCall(IERC20.transferFrom, (_alice, _app, amount)); + } + + function _encodeAddInput( + bytes memory _input + ) internal view returns (bytes memory) { + return abi.encodeCall(IInputBox.addInput, (_app, _input)); + } } diff --git a/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol b/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol index c7c08c47..5a50aefe 100644 --- a/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol +++ b/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol @@ -14,50 +14,50 @@ import {InputEncoding} from "contracts/common/InputEncoding.sol"; import {IInputRelay} from "contracts/inputs/IInputRelay.sol"; contract ApplicationAddressRelayTest is Test { - IInputBox inputBox; - IApplicationAddressRelay relay; + IInputBox _inputBox; + IApplicationAddressRelay _relay; function setUp() public { - inputBox = new InputBox(); - relay = new ApplicationAddressRelay(inputBox); + _inputBox = new InputBox(); + _relay = new ApplicationAddressRelay(_inputBox); } - function testSupportsInterface(bytes4 _randomInterfaceId) public { + function testSupportsInterface(bytes4 randomInterfaceId) public { assertTrue( - relay.supportsInterface(type(IApplicationAddressRelay).interfaceId) + _relay.supportsInterface(type(IApplicationAddressRelay).interfaceId) ); - assertTrue(relay.supportsInterface(type(IInputRelay).interfaceId)); - assertTrue(relay.supportsInterface(type(IERC165).interfaceId)); + assertTrue(_relay.supportsInterface(type(IInputRelay).interfaceId)); + assertTrue(_relay.supportsInterface(type(IERC165).interfaceId)); - assertFalse(relay.supportsInterface(bytes4(0xffffffff))); + assertFalse(_relay.supportsInterface(bytes4(0xffffffff))); vm.assume( - _randomInterfaceId != type(IApplicationAddressRelay).interfaceId + randomInterfaceId != type(IApplicationAddressRelay).interfaceId ); - vm.assume(_randomInterfaceId != type(IInputRelay).interfaceId); - vm.assume(_randomInterfaceId != type(IERC165).interfaceId); - assertFalse(relay.supportsInterface(_randomInterfaceId)); + vm.assume(randomInterfaceId != type(IInputRelay).interfaceId); + vm.assume(randomInterfaceId != type(IERC165).interfaceId); + assertFalse(_relay.supportsInterface(randomInterfaceId)); } function testGetInputBox() public { - assertEq(address(relay.getInputBox()), address(inputBox)); + assertEq(address(_relay.getInputBox()), address(_inputBox)); } - function testRelayApplicationAddress(address _app) public { + function testRelayApplicationAddress(address app) public { // Check the application's input box before - assertEq(inputBox.getNumberOfInputs(_app), 0); + assertEq(_inputBox.getNumberOfInputs(app), 0); // Construct the application address relay input - bytes memory input = abi.encodePacked(_app); + bytes memory input = abi.encodePacked(app); // Expect InputAdded to be emitted with the right arguments - vm.expectEmit(true, true, false, true, address(inputBox)); - emit IInputBox.InputAdded(_app, 0, address(relay), input); + vm.expectEmit(true, true, false, true, address(_inputBox)); + emit IInputBox.InputAdded(app, 0, address(_relay), input); // Relay the application's address - relay.relayApplicationAddress(_app); + _relay.relayApplicationAddress(app); // Check the application's input box after - assertEq(inputBox.getNumberOfInputs(_app), 1); + assertEq(_inputBox.getNumberOfInputs(app), 1); } } diff --git a/onchain/rollups/test/foundry/util/LibServerManager.sol b/onchain/rollups/test/foundry/util/LibServerManager.sol index 04381fd3..a23d064b 100644 --- a/onchain/rollups/test/foundry/util/LibServerManager.sol +++ b/onchain/rollups/test/foundry/util/LibServerManager.sol @@ -15,8 +15,6 @@ library LibServerManager { using LibServerManager for RawProof; using LibServerManager for RawProof[]; - error InvalidOutputEnum(string); - struct RawHash { bytes32 data; } @@ -47,6 +45,39 @@ library LibServerManager { RawHash vouchersEpochRootHash; } + struct OutputValidityProof { + uint256 inputIndexWithinEpoch; + uint256 outputIndexWithinInput; + bytes32 outputHashesRootHash; + bytes32 vouchersEpochRootHash; + bytes32 noticesEpochRootHash; + bytes32 machineStateHash; + bytes32[] outputHashInOutputHashesSiblings; + bytes32[] outputHashesInEpochSiblings; + } + + enum OutputEnum { + VOUCHER, + NOTICE + } + + struct Proof { + uint256 inputIndex; + uint256 outputIndex; + OutputEnum outputEnum; + OutputValidityProof validity; + bytes context; + } + + struct FinishEpochResponse { + bytes32 machineHash; + bytes32 vouchersEpochRootHash; + bytes32 noticesEpochRootHash; + Proof[] proofs; + } + + error InvalidOutputEnum(string); + function toUint(string memory s, Vm vm) internal pure returns (uint256) { return vm.parseUint(s); } @@ -140,37 +171,6 @@ library LibServerManager { }); } - struct OutputValidityProof { - uint256 inputIndexWithinEpoch; - uint256 outputIndexWithinInput; - bytes32 outputHashesRootHash; - bytes32 vouchersEpochRootHash; - bytes32 noticesEpochRootHash; - bytes32 machineStateHash; - bytes32[] outputHashInOutputHashesSiblings; - bytes32[] outputHashesInEpochSiblings; - } - - enum OutputEnum { - VOUCHER, - NOTICE - } - - struct Proof { - uint256 inputIndex; - uint256 outputIndex; - OutputEnum outputEnum; - OutputValidityProof validity; - bytes context; - } - - struct FinishEpochResponse { - bytes32 machineHash; - bytes32 vouchersEpochRootHash; - bytes32 noticesEpochRootHash; - Proof[] proofs; - } - function getInputRange( Proof[] memory proofs ) internal pure returns (InputRange memory) {