diff --git a/contracts/proxies/IProxyCreationCallback.sol b/contracts/proxies/IProxyCreationCallback.sol index 28344e75e..b70f8ed25 100644 --- a/contracts/proxies/IProxyCreationCallback.sol +++ b/contracts/proxies/IProxyCreationCallback.sol @@ -2,6 +2,17 @@ pragma solidity >=0.7.0 <0.9.0; import "./SafeProxy.sol"; +/** + * @title IProxyCreationCallback + * @dev An interface for a contract that implements a callback function to be executed after the creation of a proxy instance. + */ interface IProxyCreationCallback { + /** + * @dev Function to be called after the creation of a SafeProxy instance. + * @param proxy The newly created SafeProxy instance. + * @param _singleton The address of the singleton contract used to create the proxy. + * @param initializer The initializer function call data. + * @param saltNonce The nonce used to generate the salt for the proxy deployment. + */ function proxyCreated(SafeProxy proxy, address _singleton, bytes calldata initializer, uint256 saltNonce) external; } diff --git a/contracts/proxies/SafeProxy.sol b/contracts/proxies/SafeProxy.sol index 06d921bdb..eb2126036 100644 --- a/contracts/proxies/SafeProxy.sol +++ b/contracts/proxies/SafeProxy.sol @@ -1,22 +1,28 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -/// @title IProxy - Helper interface to access masterCopy of the Proxy on-chain -/// @author Richard Meissner - +/** + * @title IProxy - Helper interface to access the singleton address of the Proxy on-chain. + * @author Richard Meissner - @rmeissner + */ interface IProxy { function masterCopy() external view returns (address); } -/// @title SafeProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract. -/// @author Stefan George - -/// @author Richard Meissner - +/** + * @title SafeProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract. + * @author Stefan George - + * @author Richard Meissner - + */ contract SafeProxy { - // singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated. + // Singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated. // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt` address internal singleton; - /// @dev Constructor function sets address of singleton contract. - /// @param _singleton Singleton address. + /** + * @notice Constructor function sets address of singleton contract. + * @param _singleton Singleton address. + */ constructor(address _singleton) { require(_singleton != address(0), "Invalid singleton address provided"); singleton = _singleton; diff --git a/contracts/proxies/SafeProxyFactory.sol b/contracts/proxies/SafeProxyFactory.sol index 7b830701c..2ba9a14c4 100644 --- a/contracts/proxies/SafeProxyFactory.sol +++ b/contracts/proxies/SafeProxyFactory.sol @@ -4,8 +4,10 @@ pragma solidity >=0.7.0 <0.9.0; import "./SafeProxy.sol"; import "./IProxyCreationCallback.sol"; -/// @title Proxy Factory - Allows to create a new proxy contract and execute a message call to the new proxy within one transaction. -/// @author Stefan George - +/** + * @title Proxy Factory - Allows to create a new proxy contract and execute a message call to the new proxy within one transaction. + * @author Stefan George - @Georgi87 + */ contract SafeProxyFactory { event ProxyCreation(SafeProxy proxy, address singleton); @@ -14,11 +16,13 @@ contract SafeProxyFactory { return type(SafeProxy).creationCode; } - /// @dev Allows to create a new proxy contract using CREATE2. Optionally executes an initializer call to a new proxy. - /// This method is only meant as an utility to be called from other methods - /// @param _singleton Address of singleton contract. Must be deployed at the time of execution. - /// @param initializer Payload for a message call to be sent to a new proxy contract. - /// @param salt Create2 salt to use for calculating the address of the new proxy contract. + /** + * @notice Internal method to create a new proxy contract using CREATE2. Optionally executes an initializer call to a new proxy. + * @param _singleton Address of singleton contract. Must be deployed at the time of execution. + * @param initializer (Optional) Payload for a message call to be sent to a new proxy contract. + * @param salt Create2 salt to use for calculating the address of the new proxy contract. + * @return proxy Address of the new proxy contract. + */ function deployProxy(address _singleton, bytes memory initializer, bytes32 salt) internal returns (SafeProxy proxy) { require(isContract(_singleton), "Singleton contract not deployed"); @@ -39,10 +43,12 @@ contract SafeProxyFactory { } } - /// @dev Allows to create a new proxy contract and execute a message call to the new proxy within one transaction. - /// @param _singleton Address of singleton contract. Must be deployed at the time of execution. - /// @param initializer Payload for a message call to be sent to a new proxy contract. - /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. + /** + * @notice Deploys a new proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy. + * @param _singleton Address of singleton contract. Must be deployed at the time of execution. + * @param initializer Payload for a message call to be sent to a new proxy contract. + * @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. + */ function createProxyWithNonce(address _singleton, bytes memory initializer, uint256 saltNonce) public returns (SafeProxy proxy) { // If the initializer changes the proxy address should change too. Hashing the initializer data is cheaper than just concatinating it bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce)); @@ -50,11 +56,14 @@ contract SafeProxyFactory { emit ProxyCreation(proxy, _singleton); } - /// @dev Allows to create a new proxy contract that should exist only on 1 network (e.g. specific governance or admin accounts) - /// by including the chain id in the create2 salt. Such proxies cannot be created on other networks by replaying the transaction. - /// @param _singleton Address of singleton contract. Must be deployed at the time of execution. - /// @param initializer Payload for a message call to be sent to a new proxy contract. - /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. + /** + * @notice Deploys a new chain-specific proxy with `_singleton` singleton and `saltNonce` salt. Optionally executes an initializer call to a new proxy. + * @dev Allows to create a new proxy contract that should exist only on 1 network (e.g. specific governance or admin accounts) + * by including the chain id in the create2 salt. Such proxies cannot be created on other networks by replaying the transaction. + * @param _singleton Address of singleton contract. Must be deployed at the time of execution. + * @param initializer Payload for a message call to be sent to a new proxy contract. + * @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. + */ function createChainSpecificProxyWithNonce( address _singleton, bytes memory initializer, @@ -66,11 +75,14 @@ contract SafeProxyFactory { emit ProxyCreation(proxy, _singleton); } - /// @dev Allows to create a new proxy contract, execute a message call to the new proxy and call a specified callback within one transaction - /// @param _singleton Address of singleton contract. Must be deployed at the time of execution. - /// @param initializer Payload for a message call to be sent to a new proxy contract. - /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. - /// @param callback Callback that will be invoked after the new proxy contract has been successfully deployed and initialized. + /** + * @notice Deploy a new proxy with `_singleton` singleton and `saltNonce` salt. + * Optionally executes an initializer call to a new proxy and calls a specified callback address `callback`. + * @param _singleton Address of singleton contract. Must be deployed at the time of execution. + * @param initializer Payload for a message call to be sent to a new proxy contract. + * @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract. + * @param callback Callback that will be invoked after the new proxy contract has been successfully deployed and initialized. + */ function createProxyWithCallback( address _singleton, bytes memory initializer, @@ -82,8 +94,13 @@ contract SafeProxyFactory { if (address(callback) != address(0)) callback.proxyCreated(proxy, _singleton, initializer, saltNonce); } - /// @dev Returns true if `account` is a contract. - /// @param account The address being queried + /** + * @notice Returns true if `account` is a contract. + * @dev This function will return false if invoked during the constructor of a contract, + * as the code is not actually created until after the constructor finishes. + * @param account The address being queried + * @return True if `account` is a contract + */ function isContract(address account) internal view returns (bool) { uint256 size; // solhint-disable-next-line no-inline-assembly @@ -93,7 +110,10 @@ contract SafeProxyFactory { return size > 0; } - /// @dev Returns the chain id used by this contract. + /** + * @notice Returns the ID of the chain the contract is currently deployed on. + * @return The ID of the current chain as a uint256. + */ function getChainId() public view returns (uint256) { uint256 id; // solhint-disable-next-line no-inline-assembly diff --git a/contracts/test/ERC1155Token.sol b/contracts/test/ERC1155Token.sol index a0d044ea9..c74c3d690 100644 --- a/contracts/test/ERC1155Token.sol +++ b/contracts/test/ERC1155Token.sol @@ -4,6 +4,9 @@ pragma solidity >=0.7.0 <0.9.0; import "../interfaces/ERC1155TokenReceiver.sol"; import "../external/SafeMath.sol"; +/** + * @title ERC1155Token - A test ERC1155 token contract + */ contract ERC1155Token { using SafeMath for uint256; @@ -14,10 +17,10 @@ contract ERC1155Token { mapping(address => mapping(address => bool)) private _operatorApprovals; /** - @dev Get the specified address' balance for token with specified ID. - @param owner The address of the token holder - @param id ID of the token - @return The owner's balance of the token type requested + * @dev Get the specified address' balance for token with specified ID. + * @param owner The address of the token holder + * @param id ID of the token + * @return The owner's balance of the token type requested */ function balanceOf(address owner, uint256 id) public view returns (uint256) { require(owner != address(0), "ERC1155: balance query for the zero address"); @@ -25,15 +28,15 @@ contract ERC1155Token { } /** - @dev Transfers `value` amount of an `id` from the `from` address to the `to` address specified. - Caller must be approved to manage the tokens being transferred out of the `from` account. - If `to` is a smart contract, will call `onERC1155Received` on `to` and act appropriately. - @param from Source address - @param to Target address - @param id ID of the token type - @param value Transfer amount - @param data Data forwarded to `onERC1155Received` if `to` is a contract receiver - */ + * @notice Transfers `value` amount of an `id` from the `from` address to the `to` address specified. + * Caller must be approved to manage the tokens being transferred out of the `from` account. + * If `to` is a smart contract, will call `onERC1155Received` on `to` and act appropriately. + * @param from Source address + * @param to Target address + * @param id ID of the token type + * @param value Transfer amount + * @param data Data forwarded to `onERC1155Received` if `to` is a contract receiver + */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external { require(to != address(0), "ERC1155: target address must be non-zero"); require( @@ -62,11 +65,14 @@ contract ERC1155Token { _doSafeTransferAcceptanceCheck(msg.sender, address(0), to, id, value, data); } + /** + * @notice Returns true if `account` is a contract. + * @dev This function will return false if invoked during the constructor of a contract, + * as the code is not actually created until after the constructor finishes. + * @param account The address being queried + * @return True if `account` is a contract + */ function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - uint256 size; // solhint-disable-next-line no-inline-assembly assembly { @@ -75,6 +81,16 @@ contract ERC1155Token { return size > 0; } + /** + * @dev Internal function to invoke `onERC1155Received` on a target address + * The call is not executed if the target address is not a contract + * @param operator The address which initiated the transfer (i.e. msg.sender) + * @param from The address which previously owned the token + * @param to The address which will now own the token + * @param id The id of the token being transferred + * @param value The amount of tokens being transferred + * @param data Additional data with no specified format + */ function _doSafeTransferAcceptanceCheck( address operator, address from, diff --git a/contracts/test/ERC20Token.sol b/contracts/test/ERC20Token.sol index cee25d08c..ff3c7923f 100644 --- a/contracts/test/ERC20Token.sol +++ b/contracts/test/ERC20Token.sol @@ -3,7 +3,14 @@ pragma solidity >=0.6.0 <0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +/** + * @title ERC20Token + * @dev This contract is an ERC20 token contract that extends the OpenZeppelin ERC20 contract. + */ contract ERC20Token is ERC20 { + /** + * @dev Constructor that sets the name and symbol of the token and mints an initial supply to the contract deployer. + */ constructor() public ERC20("TestToken", "TT") { _mint(msg.sender, 1000000000000000); } diff --git a/contracts/test/TestHandler.sol b/contracts/test/TestHandler.sol index 9d323b1d5..4c84a34eb 100644 --- a/contracts/test/TestHandler.sol +++ b/contracts/test/TestHandler.sol @@ -3,7 +3,15 @@ pragma solidity >=0.7.0 <0.9.0; import "../handler/HandlerContext.sol"; +/** + * @title TestHandler - A test FallbackHandler contract + */ contract TestHandler is HandlerContext { + /** + * @notice Returns the sender and manager address provided by the HandlerContext + * @return sender The sender address + * @return manager The manager address + */ function dudududu() external view returns (address sender, address manager) { return (_msgSender(), _manager()); }