Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync main to release #797

Merged
merged 26 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b6a0193
build: fix explorer API url to verify contracts
CJ42 Oct 30, 2023
df653c4
Merge pull request #774 from lukso-network/ci/verify
CJ42 Oct 31, 2023
d20f17d
refactor: update isValidNonce function
skimaharvey Nov 1, 2023
2f1c4da
refactor: update for loop
skimaharvey Nov 1, 2023
34fb918
Merge pull request #782 from lukso-network/update-isValidNonce
CJ42 Nov 1, 2023
b61c7f0
test: add tests for LSP1 Type IDs
b00ste Nov 1, 2023
dceee16
Merge pull request #781 from lukso-network/DEV-8861
CJ42 Nov 1, 2023
fd23a24
fix: [L-01] Return `bytes` directly in LSP6 `_executePayload`, to pre…
CJ42 Nov 2, 2023
8f1fb95
fix: [M-03] allow setting 21 bytes under LSP17Extension data key in L…
YamenMerhi Nov 2, 2023
d6356a7
refactor: Prevent casting LSP17 Data shorter than 20 bytes (#778)
YamenMerhi Nov 2, 2023
e33477e
refactor: shorten LSP1Utils function to `notifyUniversalReceiver` (#779)
CJ42 Nov 2, 2023
aa30637
refactor: use `modifier` to check if notifier is EOA or not (#780)
CJ42 Nov 2, 2023
5d8a7af
fix: [M-02] reset `_renounceOwnershipStartedAt` on `acceptOwnership(.…
YamenMerhi Nov 2, 2023
63c06d0
refactor: [M-05] notify owner via LSP1 when confirming `renounceOwner…
b00ste Nov 2, 2023
78bb1e7
fix: [M-04 + L-02] improve empty call type checks for selector `0x000…
b00ste Nov 3, 2023
c0090c6
chore: bootstrap releases for path: . + add `Version.sol` in file to …
CJ42 Nov 3, 2023
bff93e7
fix: Adjust missing verificationData and verificationFunction (#788)
richtera Nov 6, 2023
c1574a8
chore: add notice in Natspec for `isValidSignature` (#787)
CJ42 Nov 6, 2023
a855dd1
refactor: use gas estimate in deployements scripts (#792)
skimaharvey Nov 6, 2023
e7ef125
chore: adjust Natspec comments + use mixedCase name for `modifier` (#…
CJ42 Nov 6, 2023
0b27572
refactor: add lsp1 data in ownership function hooks (#789)
YamenMerhi Nov 6, 2023
acf0a72
refactor: use `VERSION` instead of `version` (#791)
CJ42 Nov 6, 2023
d3f26ea
refactor: generate local links for `@param` & `@return` (#793)
b00ste Nov 6, 2023
4ff7b6f
chore: Refactor verification
richtera Nov 6, 2023
9ba0fcd
Merge pull request #796 from lukso-network/fix/refactor-verification
CJ42 Nov 6, 2023
6594f67
docs: Improve natspec for LSP0 (#794)
YamenMerhi Nov 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {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 @@
abstract contract LSP0ERC725AccountCore is
ERC725XCore,
ERC725YCore,
Version,
IERC1271,
ILSP0ERC725Account,
ILSP1UniversalReceiver,
Expand All @@ -95,7 +93,10 @@
* - 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 @@
*
* 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(

Check warning on line 131 in contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol

View workflow job for this annotation

GitHub Actions / build

Fallback function must be simple
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 @@
*
* - 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 @@
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 @@
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 @@
* - 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 @@

_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 @@

// 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 @@
* @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 @@
* 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 @@
) = _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 @@
}

/**
* @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 @@
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
Loading