Skip to content

Commit

Permalink
Merge pull request #797 from lukso-network/develop
Browse files Browse the repository at this point in the history
Sync main to release
  • Loading branch information
CJ42 authored Nov 7, 2023
2 parents ab26d38 + 6594f67 commit eff28af
Show file tree
Hide file tree
Showing 94 changed files with 2,426 additions and 1,124 deletions.
3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "0.12.0"
}
14 changes: 10 additions & 4 deletions constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,11 @@ export type LSP4DigitalAssetMetadata = {
export type ImageMetadata = {
width: number;
height: number;
hashFunction: string;
hash: string;
verification?: {
method: string;
data: string;
source?: string;
};
url: string;
};

Expand All @@ -134,8 +137,11 @@ export type LinkMetadata = {
};

export type AssetMetadata = {
hashFunction: string;
hash: string;
verification?: {
method: string;
data: string;
source?: string;
};
url: string;
fileType: string;
};
Expand Down
2 changes: 1 addition & 1 deletion contracts/LSP0ERC725Account/LSP0Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bytes4 constant _ERC1271_FAILVALUE = 0xffffffff;
// keccak256('LSP0ValueReceived')
bytes32 constant _TYPEID_LSP0_VALUE_RECEIVED = 0x9c4705229491d365fb5434052e12a386d6771d976bea61070a8c694e8affea3d;

// Ownerhsip Transfer Type IDs
// Ownership Transfer Type IDs

// keccak256('LSP0OwnershipTransferStarted')
bytes32 constant _TYPEID_LSP0_OwnershipTransferStarted = 0xe17117c9d2665d1dbeb479ed8058bbebde3c50ac50e2e65619f60006caac6926;
Expand Down
10 changes: 7 additions & 3 deletions contracts/LSP0ERC725Account/LSP0ERC725Account.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
pragma solidity ^0.8.4;

// modules
import {Version} from "../Version.sol";
import {LSP0ERC725AccountCore} from "./LSP0ERC725AccountCore.sol";
import {
OwnableUnset
} from "@erc725/smart-contracts/contracts/custom/OwnableUnset.sol";

// constants

import {_TYPEID_LSP0_VALUE_RECEIVED} from "./LSP0Constants.sol";

/**
Expand All @@ -26,10 +26,14 @@ import {_TYPEID_LSP0_VALUE_RECEIVED} from "./LSP0Constants.sol";
* - Extending the account with new functions and interfaceIds of future standards using [LSP-17-ContractExtension]
* - Verifying calls on the owner to make it easier to interact with the account directly using [LSP-20-CallVerification]
*/
contract LSP0ERC725Account is LSP0ERC725AccountCore {
contract LSP0ERC725Account is LSP0ERC725AccountCore, Version {
/**
* @notice Deploying a LSP0ERC725Account contract with owner set to address `initialOwner`.
* @dev Set `initialOwner` as the contract owner. The `constructor` also allows funding the contract on deployment.
*
* @dev Set `initialOwner` as the contract owner.
* - The `constructor` also allows funding the contract on deployment.
* - The `initialOwner` will then be allowed to call protected functions marked with the `onlyOwner` modifier.
*
* @param initialOwner The owner of the contract.
*
* @custom:events
Expand Down
103 changes: 62 additions & 41 deletions contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {LSP1Utils} from "../LSP1UniversalReceiver/LSP1Utils.sol";
import {LSP2Utils} from "../LSP2ERC725YJSONSchema/LSP2Utils.sol";

// modules
import {Version} from "../Version.sol";
import {ERC725YCore} from "@erc725/smart-contracts/contracts/ERC725YCore.sol";
import {ERC725XCore} from "@erc725/smart-contracts/contracts/ERC725XCore.sol";
import {
Expand Down Expand Up @@ -78,7 +77,6 @@ import {
abstract contract LSP0ERC725AccountCore is
ERC725XCore,
ERC725YCore,
Version,
IERC1271,
ILSP0ERC725Account,
ILSP1UniversalReceiver,
Expand All @@ -95,7 +93,10 @@ abstract contract LSP0ERC725AccountCore is
* - When receiving some native tokens without any additional data.
* - On empty calls to the contract.
*
* @custom:events {UniversalReceiver} event when receiving native tokens.
* @custom:info This function internally delegates the handling of native tokens to the {universalReceiver} function
* passing `_TYPEID_LSP0_VALUE_RECEIVED` as typeId and an empty bytes array as received data.
*
* @custom:events Emits a {UniversalReceiver} event when the `universalReceiver` logic is executed upon receiving native tokens.
*/
receive() external payable virtual {
if (msg.value != 0) {
Expand All @@ -122,16 +123,19 @@ abstract contract LSP0ERC725AccountCore is
*
* 2. If the data sent to this function is of length less than 4 bytes (not a function selector), return.
*
* @custom:info Whenever the call is associated with native tokens, the function will delegate the handling of native tokens internally to the {universalReceiver} function
* passing `_TYPEID_LSP0_VALUE_RECEIVED` as typeId and the calldata as received data, except when the native token will be sent directly to the extension.
*
* @custom:events {UniversalReceiver} event when receiving native tokens and extension function selector is not found or not payable.
*/
// solhint-disable-next-line no-complex-fallback
fallback(
bytes calldata callData
) external payable virtual returns (bytes memory) {
if (msg.data.length < 4) {
// if value is associated with the extension call, use the universalReceiver
if (msg.value != 0)
if (msg.value != 0) {
universalReceiver(_TYPEID_LSP0_VALUE_RECEIVED, callData);
}
return "";
}

Expand Down Expand Up @@ -434,6 +438,8 @@ abstract contract LSP0ERC725AccountCore is
*
* - If yes, call this address with the typeId and data (params), along with additional calldata consisting of 20 bytes of `msg.sender` and 32 bytes of `msg.value`. If not, continue the execution of the function.
*
* This function delegates internally the handling of native tokens to the {universalReceiver} function itself passing `_TYPEID_LSP0_VALUE_RECEIVED` as typeId and the calldata as received data.
*
* @param typeId The type of call received.
* @param receivedData The data received.
*
Expand Down Expand Up @@ -541,9 +547,9 @@ abstract contract LSP0ERC725AccountCore is
emit OwnershipTransferStarted(currentOwner, pendingNewOwner);

// notify the pending owner through LSP1
pendingNewOwner.tryNotifyUniversalReceiver(
pendingNewOwner.notifyUniversalReceiver(
_TYPEID_LSP0_OwnershipTransferStarted,
""
abi.encode(currentOwner, pendingNewOwner)
);

// reset the transfer ownership lock
Expand All @@ -561,9 +567,9 @@ abstract contract LSP0ERC725AccountCore is
emit OwnershipTransferStarted(currentOwner, pendingNewOwner);

// notify the pending owner through LSP1
pendingNewOwner.tryNotifyUniversalReceiver(
pendingNewOwner.notifyUniversalReceiver(
_TYPEID_LSP0_OwnershipTransferStarted,
""
abi.encode(currentOwner, pendingNewOwner)
);

// reset the transfer ownership lock
Expand All @@ -585,7 +591,7 @@ abstract contract LSP0ERC725AccountCore is
* - When notifying the previous owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_SenderNotification].
* - When notifying the new owner via LSP1, the typeId used must be the `keccak256(...)` hash of [LSP0OwnershipTransferred_RecipientNotification].
*/
function acceptOwnership() public virtual override NotInTransferOwnership {
function acceptOwnership() public virtual override notInTransferOwnership {
address previousOwner = owner();
address pendingOwnerAddress = pendingOwner();

Expand All @@ -598,20 +604,21 @@ abstract contract LSP0ERC725AccountCore is

_setOwner(pendingOwnerAddress);
delete _pendingOwner;
delete _renounceOwnershipStartedAt;
} else {
_acceptOwnership();
}

// notify the previous owner if supports LSP1
previousOwner.tryNotifyUniversalReceiver(
previousOwner.notifyUniversalReceiver(
_TYPEID_LSP0_OwnershipTransferred_SenderNotification,
""
abi.encode(previousOwner, pendingOwnerAddress)
);

// notify the pending owner if supports LSP1
pendingOwnerAddress.tryNotifyUniversalReceiver(
pendingOwnerAddress.notifyUniversalReceiver(
_TYPEID_LSP0_OwnershipTransferred_RecipientNotification,
""
abi.encode(previousOwner, pendingOwnerAddress)
);

// If msg.sender != pendingOwnerAddress & verifyAfter is true, Call {lsp20VerifyCallResult} on the new owner
Expand All @@ -638,27 +645,35 @@ abstract contract LSP0ERC725AccountCore is

// If the caller is the owner perform renounceOwnership directly
if (msg.sender == accountOwner) {
return LSP14Ownable2Step._renounceOwnership();
}
address previousOwner = owner();
LSP14Ownable2Step._renounceOwnership();

// If the caller is not the owner, call {lsp20VerifyCall} on the owner
// Depending on the returnedStatus, a second call is done after transferring ownership
bool verifyAfter = _verifyCall(accountOwner);
if (owner() == address(0)) {
previousOwner.notifyUniversalReceiver(
_TYPEID_LSP0_OwnershipTransferred_SenderNotification,
abi.encode(accountOwner, address(0))
);
}
} else {
// If the caller is not the owner, call {lsp20VerifyCall} on the owner
// Depending on the returnedStatus, a second call is done after transferring ownership
bool verifyAfter = _verifyCall(accountOwner);

address previousOwner = owner();
LSP14Ownable2Step._renounceOwnership();
address previousOwner = owner();
LSP14Ownable2Step._renounceOwnership();

if (owner() == address(0)) {
previousOwner.tryNotifyUniversalReceiver(
_TYPEID_LSP0_OwnershipTransferred_SenderNotification,
""
);
}
if (owner() == address(0)) {
previousOwner.notifyUniversalReceiver(
_TYPEID_LSP0_OwnershipTransferred_SenderNotification,
abi.encode(accountOwner, address(0))
);
}

// If verifyAfter is true, Call {lsp20VerifyCallResult} on the owner
// The transferOwnership function does not return, second parameter of {_verifyCallResult} will be empty
if (verifyAfter) {
_verifyCallResult(accountOwner, "");
// If verifyAfter is true, Call {lsp20VerifyCallResult} on the owner
// The transferOwnership function does not return, second parameter of {_verifyCallResult} will be empty
if (verifyAfter) {
_verifyCallResult(accountOwner, "");
}
}
}

Expand Down Expand Up @@ -717,6 +732,11 @@ abstract contract LSP0ERC725AccountCore is
* @param signature A signature that can validate the previous parameter (Hash).
*
* @return returnedStatus A `bytes4` value that indicates if the signature is valid or not.
*
* @custom:warning This function does not enforce by default the inclusion of the address of this contract in the signature digest.
* It is recommended that protocols or applications using this contract include the targeted address (= this contract) in the data to sign.
* To ensure that a signature is valid for a specific LSP0ERC725Account and prevent signatures from the same EOA to be replayed
* across different LSP0ERC725Accounts.
*/
function isValidSignature(
bytes32 dataHash,
Expand Down Expand Up @@ -775,14 +795,7 @@ abstract contract LSP0ERC725AccountCore is
* If there is an extension for the function selector being called, it calls the extension with the
* `CALL` opcode, passing the `msg.data` appended with the 20 bytes of the {msg.sender} and 32 bytes of the `msg.value`.
*
* @custom:hint This function does not forward to the extension contract the `msg.value` received by the contract that inherits `LSP17Extendable`.
* If you would like to forward the `msg.value` to the extension contract, you can override the code of this internal function as follow:
*
* ```solidity
* (bool success, bytes memory result) = extension.call{value: msg.value}(
* abi.encodePacked(callData, msg.sender, msg.value)
* );
* ```
* @custom:hint If you would like to forward the `msg.value` to the extension contract, you should store an additional `0x01` byte after the address of the extension under the corresponding LSP17 data key.
*/
function _fallbackLSP17Extendable(
bytes calldata callData
Expand All @@ -794,8 +807,9 @@ abstract contract LSP0ERC725AccountCore is
) = _getExtensionAndForwardValue(msg.sig);

// if value is associated with the extension call and extension function selector is not payable, use the universalReceiver
if (msg.value != 0 && !isForwardingValue)
if (msg.value != 0 && !isForwardingValue) {
universalReceiver(_TYPEID_LSP0_VALUE_RECEIVED, callData);
}

// if no extension was found for bytes4(0) return don't revert
if (msg.sig == bytes4(0) && extension == address(0)) return "";
Expand All @@ -821,9 +835,10 @@ abstract contract LSP0ERC725AccountCore is
}

/**
* @dev Returns the extension address stored under the following data key:
* @dev Returns the extension address and the boolean indicating whether to forward the value received to the extension, stored under the following data key:
* - {_LSP17_EXTENSION_PREFIX} + `<bytes4>` (Check [LSP2-ERC725YJSONSchema] for encoding the data key).
* - If no extension is stored, returns the address(0).
* - If the stored value is 20 bytes, return false for the boolean
*/
function _getExtensionAndForwardValue(
bytes4 functionSelector
Expand All @@ -838,6 +853,12 @@ abstract contract LSP0ERC725AccountCore is
mappedExtensionDataKey
);

// Prevent casting data shorter than 20 bytes to an address to avoid
// unintentionally calling a different extension, return address(0) instead.
if (extensionData.length < 20) {
return (address(0), false);
}

// CHECK if the `extensionData` is 21 bytes long
// - 20 bytes = extension's address
// - 1 byte `0x01` as a boolean indicating if the contract should forward the value to the extension or not
Expand Down
3 changes: 2 additions & 1 deletion contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.4;

// modules
import {Version} from "../Version.sol";
import {
LSP0ERC725AccountInitAbstract
} from "./LSP0ERC725AccountInitAbstract.sol";
Expand All @@ -21,7 +22,7 @@ import {
* - Extending the account with new functions and interfaceIds of future standards using [LSP-17-ContractExtension]
* - Verifying calls on the owner to make it easier to interact with the account directly using [LSP-20-CallVerification]
*/
contract LSP0ERC725AccountInit is LSP0ERC725AccountInitAbstract {
contract LSP0ERC725AccountInit is LSP0ERC725AccountInitAbstract, Version {
/**
* @notice deploying a `LSP0ERC725AccountInit` base contract to be used behind proxy
* @dev Locks the base contract on deployment, so that it cannot be initialized, owned and controlled by anyone after it has been deployed. This is intended so that the sole purpose of this contract is to be used as a base contract behind a proxy.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ abstract contract LSP0ERC725AccountInitAbstract is
{
/**
* @dev Set `initialOwner` as the contract owner.
* The `initialOwner` will then be allowed to call protected functions marked with the `onlyOwner` modifier.
*
* @param initialOwner The owner of the contract.
*
* @custom:warning ERC725X & ERC725Y parent contracts are not initialised as they don't have non-zero initial state. If you decide to add non-zero initial state to any of those contracts, you must initialize them here.
* @custom:warning ERC725X & ERC725Y parent contracts are not initialixed as they don't have non-zero initial state.
* If you decide to add non-zero initial state to any of those contracts, you MUST initialize them here.
*
* @custom:events
* - {UniversalReceiver} event when funding the contract on deployment.
Expand Down
Loading

0 comments on commit eff28af

Please sign in to comment.