Skip to content

Commit

Permalink
Refactor/LSP0ERC725Account (#99)
Browse files Browse the repository at this point in the history
* build: upgrade OZ and erc725-sc packages

* feat: add LSP0ERC725Account contracts

* feat: add ERC725Utils and Utils lib

* fix: remove unused parameter in ERC725Utils

* fix: fix import path in LSP6Utils

* feat: add InitAbstract contracts

After OZ breaking change concerning how to initialize proxies, InitAbstract contracts are for inheritance and normal Init contracts are for deploying

* test: fix events name failing tests

name of the args of the events changed, so we changed them in the tests

* test: rename to LSP0ERC725Account test

* fix: fix OZ initialize breaking change

* fix: fix path importing conflicts

* docs: add generated docs

* build: upgrade package-lock.json

* refactor: use IERC1271 from OZ-contracts

* docs: add generated docs
  • Loading branch information
YamenMerhi authored Jan 17, 2022
1 parent 9d46299 commit 6c11e54
Show file tree
Hide file tree
Showing 141 changed files with 7,219 additions and 937 deletions.
10 changes: 5 additions & 5 deletions contracts/Helpers/CalculateSelectors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import "../LSP9Vault/LSP9Vault.sol";
import "../LSP6KeyManager/ILSP6KeyManager.sol";
import "../LSP7DigitalAsset/ILSP7DigitalAsset.sol";
import "../LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol";
import "@erc725/smart-contracts/contracts/interfaces/IERC1271.sol";
import "@erc725/smart-contracts/contracts/interfaces/ILSP1_UniversalReceiver.sol";
import "@erc725/smart-contracts/contracts/interfaces/ILSP1_UniversalReceiverDelegate.sol";
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
import "../LSP1UniversalReceiver/ILSP1UniversalReceiver.sol";
import "../LSP1UniversalReceiver/ILSP1UniversalReceiverDelegate.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";

Expand All @@ -22,7 +22,7 @@ import "../LSP8IdentifiableDigitalAsset/LSP8Constants.sol";

contract CalculateERC165Selectors {
function calculateSelectorLSP1() public pure returns (bytes4) {
bytes4 selector = type(ILSP1).interfaceId;
bytes4 selector = type(ILSP1UniversalReceiver).interfaceId;
require(
selector == _INTERFACEID_LSP1,
"_LSP1_INTERFACE_ID does not match type(ILSP1).interfaceId"
Expand All @@ -32,7 +32,7 @@ contract CalculateERC165Selectors {
}

function calculateSelectorLSP1Delegate() public pure returns (bytes4) {
bytes4 selector = type(ILSP1Delegate).interfaceId;
bytes4 selector = type(ILSP1UniversalReceiverDelegate).interfaceId;
require(
selector == _INTERFACEID_LSP1_DELEGATE,
"_LSP1_DELEGATE_INTERFACE_ID does not match type(ILSP1Delegate).interfaceId"
Expand Down
8 changes: 4 additions & 4 deletions contracts/Helpers/Tokens/LSP7CappedSupplyInitTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
pragma solidity ^0.8.0;

// modules
import "../../LSP7DigitalAsset/extensions/LSP7CappedSupplyInit.sol";
import "../../LSP7DigitalAsset/extensions/LSP7CappedSupplyInitAbstract.sol";

contract LSP7CappedSupplyInitTester is LSP7CappedSupplyInit {
contract LSP7CappedSupplyInitTester is LSP7CappedSupplyInitAbstract {
function initialize(
string memory name,
string memory symbol,
address newOwner,
uint256 tokenSupplyCap
) public virtual initializer {
LSP7DigitalAssetInit.initialize(name, symbol, newOwner, true);
LSP7CappedSupplyInit.initialize(tokenSupplyCap);
LSP7DigitalAssetInitAbstract.initialize(name, symbol, newOwner, true);
LSP7CappedSupplyInitAbstract.initialize(tokenSupplyCap);
}

function mint(address to, uint256 amount) public {
Expand Down
6 changes: 3 additions & 3 deletions contracts/Helpers/Tokens/LSP7InitTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

pragma solidity ^0.8.0;

import "../../LSP7DigitalAsset/LSP7DigitalAssetInit.sol";
import "../../LSP7DigitalAsset/LSP7DigitalAssetInitAbstract.sol";

contract LSP7InitTester is LSP7DigitalAssetInit {
contract LSP7InitTester is LSP7DigitalAssetInitAbstract {
function initialize(
string memory name,
string memory symbol,
address newOwner
) public override initializer {
LSP7DigitalAssetInit.initialize(name, symbol, newOwner, false);
LSP7DigitalAssetInitAbstract.initialize(name, symbol, newOwner, false);
}

function mint(
Expand Down
12 changes: 8 additions & 4 deletions contracts/Helpers/Tokens/LSP8CappedSupplyInitTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
pragma solidity ^0.8.0;

// modules
import "../../LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupplyInit.sol";
import "../../LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupplyInitAbstract.sol";

contract LSP8CappedSupplyInitTester is LSP8CappedSupplyInit {
contract LSP8CappedSupplyInitTester is LSP8CappedSupplyInitAbstract {
function initialize(
string memory name,
string memory symbol,
address newOwner,
uint256 tokenSupplyCap
) public virtual initializer {
LSP8IdentifiableDigitalAssetInit.initialize(name, symbol, newOwner);
LSP8CappedSupplyInit.initialize(tokenSupplyCap);
LSP8IdentifiableDigitalAssetInitAbstract.initialize(
name,
symbol,
newOwner
);
LSP8CappedSupplyInitAbstract.initialize(tokenSupplyCap);
}

function mint(address to, bytes32 tokenId) public {
Expand Down
10 changes: 7 additions & 3 deletions contracts/Helpers/Tokens/LSP8InitTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

pragma solidity ^0.8.0;

import "../../LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetInit.sol";
import "../../LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetInitAbstract.sol";

contract LSP8InitTester is LSP8IdentifiableDigitalAssetInit {
contract LSP8InitTester is LSP8IdentifiableDigitalAssetInitAbstract {
function initialize(
string memory name,
string memory symbol,
address newOwner
) public override initializer {
LSP8IdentifiableDigitalAssetInit.initialize(name, symbol, newOwner);
LSP8IdentifiableDigitalAssetInitAbstract.initialize(
name,
symbol,
newOwner
);
}

function mint(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.0;

// interfaces
import "@erc725/smart-contracts/contracts/interfaces/ILSP1_UniversalReceiverDelegate.sol";
import "../../LSP1UniversalReceiver/ILSP1UniversalReceiverDelegate.sol";

// modules
import "../Registries/AddressRegistry.sol";
Expand All @@ -12,7 +12,7 @@ import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
contract UniversalReceiverAddressStoreInit is
Initializable,
ERC165Storage,
ILSP1Delegate,
ILSP1UniversalReceiverDelegate,
AddressRegistry
{
using EnumerableSet for EnumerableSet.AddressSet;
Expand Down
14 changes: 14 additions & 0 deletions contracts/LSP0ERC725Account/LSP0Constants.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

// >> INTERFACES

bytes4 constant _INTERFACE_ID_ERC725ACCOUNT = 0x63cb749b;

bytes4 constant _INTERFACE_ID_ERC1271 = 0x1626ba7e;

// >> OTHER

// ERC1271 - Standard Signature Validation
bytes4 constant _ERC1271MAGICVALUE = 0x1626ba7e;
bytes4 constant _ERC1271FAILVALUE = 0xffffffff;
23 changes: 23 additions & 0 deletions contracts/LSP0ERC725Account/LSP0ERC725Account.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

// modules
import "./LSP0ERC725AccountCore.sol";
import "@erc725/smart-contracts/contracts/ERC725.sol";

/**
* @title Implementation of ERC725Account
* @author Fabian Vogelsteller <[email protected]>, Jean Cavallera (CJ42), Yamen Merhi (YamenMerhi)
* @dev Bundles ERC725X and ERC725Y, ERC1271 and LSP1UniversalReceiver and allows receiving native tokens
*/
contract LSP0ERC725Account is ERC725, LSP0ERC725AccountCore {
/**
* @notice Sets the owner of the contract and register ERC725Account, ERC1271 and LSP1UniversalReceiver interfacesId
* @param _newOwner the owner of the contract
*/
constructor(address _newOwner) ERC725(_newOwner) {
_registerInterface(_INTERFACE_ID_ERC725ACCOUNT);
_registerInterface(_INTERFACE_ID_ERC1271);
_registerInterface(_INTERFACEID_LSP1);
}
}
119 changes: 119 additions & 0 deletions contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

// interfaces
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
import "../LSP1UniversalReceiver/ILSP1UniversalReceiver.sol";
import "../LSP1UniversalReceiver/ILSP1UniversalReceiverDelegate.sol";

// modules

import "@erc725/smart-contracts/contracts/ERC725YCore.sol";
import "@erc725/smart-contracts/contracts/ERC725XCore.sol";

// libraries
import "../Utils/UtilsLib.sol";
import "../Utils/ERC725Utils.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

// constants
import "../LSP1UniversalReceiver/LSP1Constants.sol";
import "../LSP0ERC725Account/LSP0Constants.sol";

/**
* @title Core Implementation of ERC725Account
* @author Fabian Vogelsteller <[email protected]>, Jean Cavallera (CJ42), Yamen Merhi (YamenMerhi)
* @dev Bundles ERC725X and ERC725Y, ERC1271 and LSP1UniversalReceiver and allows receiving native tokens
*/
abstract contract LSP0ERC725AccountCore is
ERC725XCore,
ERC725YCore,
ILSP1UniversalReceiver,
IERC1271
{
using ERC725Utils for IERC725Y;

event ValueReceived(address indexed sender, uint256 indexed value);

receive() external payable {
emit ValueReceived(_msgSender(), msg.value);
}

// TODO to be discussed
// function fallback()
// public
// {
// address to = owner();
// assembly {
// calldatacopy(0, 0, calldatasize())
// let result := staticcall(gas(), to, 0, calldatasize(), 0, 0)
// returndatacopy(0, 0, returndatasize())
// switch result
// case 0 { revert (0, returndatasize()) }
// default { return (0, returndatasize()) }
// }
// }

/**
* @notice Checks if an owner signed `_data`.
* ERC1271 interface.
*
* @param _hash hash of the data signed//Arbitrary length data signed on the behalf of address(this)
* @param _signature owner's signature(s) of the data
*/
function isValidSignature(bytes32 _hash, bytes memory _signature)
public
view
override
returns (bytes4 magicValue)
{
// prettier-ignore
// if OWNER is a contract
if (UtilsLib.isContract(owner())) {
return
supportsInterface(_INTERFACE_ID_ERC1271)
? IERC1271(owner()).isValidSignature(_hash, _signature)
: _ERC1271FAILVALUE;
// if OWNER is a key
} else {
return
owner() == ECDSA.recover(_hash, _signature)
? _INTERFACE_ID_ERC1271
: _ERC1271FAILVALUE;
}
}

function universalReceiver(bytes32 _typeId, bytes calldata _data)
external
virtual
override
returns (bytes memory returnValue)
{
bytes memory receiverData = IERC725Y(this).getDataSingle(
_LSP1_UNIVERSAL_RECEIVER_DELEGATE_KEY
);
returnValue = "";

// call external contract
if (receiverData.length == 20) {
address universalReceiverAddress = BytesLib.toAddress(
receiverData,
0
);

if (
ERC165(universalReceiverAddress).supportsInterface(
_INTERFACEID_LSP1_DELEGATE
)
) {
returnValue = ILSP1UniversalReceiverDelegate(
universalReceiverAddress
).universalReceiverDelegate(_msgSender(), _typeId, _data);
}
}

emit UniversalReceiver(_msgSender(), _typeId, returnValue, _data);

return returnValue;
}
}
20 changes: 20 additions & 0 deletions contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

// modules
import "./LSP0ERC725AccountInitAbstract.sol";

/**
* @title Deployable Proxy Implementation of ERC725Account
* @author Fabian Vogelsteller <[email protected]>, Jean Cavallera (CJ42), Yamen Merhi (YamenMerhi)
* @dev Bundles ERC725X and ERC725Y, ERC1271 and LSP1UniversalReceiver and allows receiving native tokens
*/
contract LSP0ERC725AccountInit is LSP0ERC725AccountInitAbstract {
/**
* @inheritdoc LSP0ERC725AccountInitAbstract
*/

function initialize(address _newOwner) public virtual override initializer {
LSP0ERC725AccountInitAbstract.initialize(_newOwner);
}
}
33 changes: 33 additions & 0 deletions contracts/LSP0ERC725Account/LSP0ERC725AccountInitAbstract.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

// modules
import "@erc725/smart-contracts/contracts/ERC725InitAbstract.sol";
import "./LSP0ERC725AccountCore.sol";

/**
* @title Inheritable Proxy Implementation of ERC725Account
* @author Fabian Vogelsteller <[email protected]>, Jean Cavallera (CJ42), Yamen Merhi (YamenMerhi)
* @dev Bundles ERC725X and ERC725Y, ERC1271 and LSP1UniversalReceiver and allows receiving native tokens
*/
abstract contract LSP0ERC725AccountInitAbstract is
ERC725InitAbstract,
LSP0ERC725AccountCore
{
/**
* @notice Sets the owner of the contract and register ERC725Account, ERC1271 and LSP1UniversalReceiver interfacesId
* @param _newOwner the owner of the contract
*/
function initialize(address _newOwner)
public
virtual
override
onlyInitializing
{
ERC725InitAbstract.initialize(_newOwner);

_registerInterface(_INTERFACE_ID_ERC725ACCOUNT);
_registerInterface(_INTERFACE_ID_ERC1271);
_registerInterface(_INTERFACEID_LSP1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "../../../LSP6KeyManager/ILSP6KeyManager.sol";
import "../../../LSP7DigitalAsset/ILSP7DigitalAsset.sol";

// libraries
import "@erc725/smart-contracts/contracts/utils/ERC725Utils.sol";
import "../../../Utils/ERC725Utils.sol";

// constants
import "../../LSP1Constants.sol";
Expand Down Expand Up @@ -83,8 +83,7 @@ abstract contract TokenAndVaultHandlingContract {
IERC725Y(msg.sender),
arrayKey,
mapHash,
mapKey,
interfaceID
mapKey
);

result = _executeViaKeyManager(
Expand All @@ -107,8 +106,7 @@ abstract contract TokenAndVaultHandlingContract {
IERC725Y(msg.sender),
arrayKey,
mapHash,
mapKey,
interfaceID
mapKey
);

result = _executeViaKeyManager(
Expand Down
Loading

0 comments on commit 6c11e54

Please sign in to comment.