GithubHelp home page GithubHelp logo

lukso-network / lips Goto Github PK

View Code? Open in Web Editor NEW
91.0 15.0 43.0 2.05 MB

LUKSO Improvement Proposals. Repository for the LUKSO Blockchain Improvement Proposals (LIPs) and LUKSO Standards Process (LSP).

standards evm ethereum solidity erc eip lip lsp

lips's People

Contributors

0xchijioke avatar anettrolikova avatar ankitkumar9018 avatar aurelianoa avatar b00ste avatar callumgrindle avatar cj42 avatar claudiozone avatar dzbo avatar fhildeb avatar frozeman avatar hugoo avatar jakeprins avatar jeneavranceanu avatar jgcarv avatar jxyang44 avatar kirikev avatar lykhonis avatar magalimorin18 avatar mattgstevens avatar mitchtodo avatar omahs avatar richtera avatar rryter avatar samuel-videau avatar skimaharvey avatar yamenmerhi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lips's Issues

[LSP6] Add EIP-1271 verification mechanism for relay calls

What this issue is about?

Currently, a controller address having permission, either a contract or an EOA can use the execute(..) function to execute a payload on the target contract.

Image1111

In the case of executeRelayCall(..) it's a little bit different since the only verification method supported is verification through ECDSA. This means the relay call is only supported for EOAs that have permissions and not for contracts that have permissions.

That means EOAs that have permissions can sign messages and hand them to a relayer, and this relayer entity can submit the signature and the payload and execute successfully.

IMAGE222

For contracts that have permissions, there is no way to pass signed messages by the contract as the contract can't sign.

DFEEF

Going further, that means we cannot create an ecosystem of meta-tx, taking efficiency into consideration because each contract that has permissions needs to find a meta-tx way to make a 3rd party relayer pay for his tx.


We can provide an example with LSP0, If Bob has an LSP0 and have two controllers, his EOA and Alice's UP.

cece

If Bob wants to execute a payload without paying gas fees, he can sign the payload and submit it to a relayer that can execute his payload on the KeyManager, the KeyManager receiving the signature and the payload can verify through ECDSA that the signer is Bob that have all permissions to execute successfully.

vrvr

If Alice wants to create a tx on Bob's LSP0 and her LSP0 is owned by her EOA, there is no way for her to submit this tx through a relayer, she is forced to execute from her EOA by paying gas fees. And the only way for her to execute without paying is to have her LSP0 owned by an LSP6 that supports relay call, so the execution would be something like this:

hdbehdbe

While we push for an ecosystem full of contract-to-contract interactivity with smart contract accounts and taking into consideration efficiency, there is a need to verify signed messages of smart contracts to support all relay calls type and simplify the execution chain.

Solution

One way to solve this issue is checking if a signature of a contract is valid through ERC1271, in this way relayers instead of just executing payloads of EOAs controllers, can also execute payloads of contracts controllers based on their logic of verifying signature with ERC1271.

nfjrfnr

Going back to Alice and Bob example of LSP0, now Alice having her LSP0 owned by her EOA can make a relay call, by going with the logic inside the isValidSignature of her LSP0 contract, which says that if the owner is an EOA, then the contract checks if the signature is valid through ECDSA and returning the address of the owner.

cdcc

And if Alice's LSP0 is owned by an LSP6, the verification mechanism of isValidSignature(..) in LSP0 will call isValidSignature(..) on LSP6, validating the call if the address recovered through ECDSA have SIGN Permission.

Thinking that all LSP0 will be associated with LSP6 is misleading, also thinking that all contracts controllers will only be LSP0 is misleading, we can have some sort of logic-based contracts that can validate signatures based on some sort of time-lock + signatures or secret hash + signatures, etc.. , that's why we need to allow relay contract execution regardless of the type of the contract, if the latter supports EIP-1271.

Changes Needed

To Allow this behavior, non of the core logic of the KeyManager needs to be changed, it's either having a new overloaded function that takes the address of the contract controller that is supposed to support ERC1271, or we can add the contract address to the first parameter of executeRelayCall, and inside the function:

  • Checking the length of the signature param
  • If 65 it's an EOA verification through ECDSA (what we currently have)
  • If the length is 85 then it's the signature + an address, which resolves the verification through 1271 by calling isValidSignature(..) on the address (last 20 bytes).

If this method seems too hacky we can have separate functions, that have an additional address contract parameter.

[LSP2] add `enum` as `valueContent` (or `valueType`?)

When looking at the following JSON Schema for the metadata key LSP8TokenIdType

{
    "name": "LSP8TokenIdType",
    "key": "0x715f248956de7ce65e94d9d836bfead479f7e70d69b718d47bfe7b00e05b4fe4",
    "keyType": "Singleton",
    "valueType": "uint256",
    "valueContent": "Number"
}

It is not clear by looking directly at the schema that there is only 3 possible values that can be stored under this data key.

image

It would be useful to identify when there are only 3 possible enumerable values.

It should also be flexible enough to allow possible enum values like:

  • numbers (e.g: Player level = 1, 2 or 3)
  • literal string (e.g: Proposal = Pending, Queued, Active, Expired)
  • literal bytesN

Related to:

LSP3 and LSP4 image references

Lets find a better way to reference images in the following standards:

The current way is:

{
    "LSP3Profile": {
        "profileImage": "URI", // The profile image represents one image representing the profile, like a person image, a company logo or avatar.
        "profileImageHash": "keccak256",
        "backgroundImage": "URI", // The background is an image that can be used in conjunction with profile image to give a more personal look to the profile.
                                  // Websites displaying the profile have to choose how or if, to use this image.
        "backgroundImageHash": "keccak256",
        "description": "string" // A description, describing the person, company, organisation and/or creator of the profile.
    }
}

We should see how we can improve that to support multiple image resolutions per image, and store the hashes properly per image. This standard is a good reference for that: https://eips.ethereum.org/EIPS/eip-2477

[LSP1] Gas Limit for Universal Receivers

Gas Limit for Universal Receivers

Problem

A primary concern for individuals interacting with contracts utilizing the LSP1 universalReceiver(..) function is the potential for significant gas consumption on the contract being notified. In such scenarios, the transaction initiator (referenced by tx.origin) bears the high gas fees due to the logic executed in the notified contract.

Example

To illustrate, consider a scenario where a user transfers a token. The token contract, in turn, notifies the recipient via the universalReceiver(..) function. If this function contains complex logic, it could result in substantial gas consumption, forcing the sender to pay very high transaction fees.

How this problem is supposed to be solved ?

[LSP7] Allowance Double-Spend Exploit in `authorizeOperator(..)`

What this issue is about?

As it presently is constructed, the contract is vulnerable to the allowance double-spend exploit, as with other ERC20/LSP7 tokens.

Exploit Scenario: 1. Alice allows Bob to transfer N amount of Alice's tokens (N>0) by calling the authorizeOperator(..) method on LSP7 smart contract (passing Bob's address and N as method arguments).

After some time, Alice decides to change from N to M (M>0) the number of Alice's tokens Bob is allowed to transfer, so she calls the authorizeOperator(..) method again, this time passing Bob's address and M as method arguments.

Bob notices Alice's second transaction before it was mined and quickly sends another transaction that calls the transfer(..) method to transfer N Alice's tokens somewhere.

If Bob's transaction will be executed before Alice's transaction, then Bob will successfully transfer N Alice's tokens and will gain the ability to transfer another M tokens.

Before Alice notices any irregularities, Bob calls the transfer(..) method again, this time to transfer M Alice's tokens.

How to solve?

The front-running problem cannot be mitigated in the blockchain space but some work around can be done at the standard level or smart contract level to eliminate the risk of front-running.

One possible solution could be adding increaseAllowance(..) and decreaseAllowance function alike from ERC20.
Another one could be changing the behavior of authorizeOperator(..) to just add the authorized amount to the last amount present. But the problem will still exist when we want to decrease the allowance of an address.

For now, this risk could be mitigated by calling revokeOperator(..) function first, and then re-calling authorizeOperator with the whole amount we want to authorize the operator for.

To be discussed..

[LSP8] Define if `0x` prefix should be added to `LSP8MetadataBaseURI`

For LSP8TokenIdFormat 3 or 4 (= bytes32)

Should we construct the final URI like this:

http://mybase.uri/e5fe3851d597a3aa8bbdf8d8289eb9789ca2c34da7a7c3d0a7c442a87b81d5c2

Or like this?

http://mybase.uri/0xe5fe3851d597a3aa8bbdf8d8289eb9789ca2c34da7a7c3d0a7c442a87b81d5c2

Depending on choice, write down the following note in the LSP8 specs under the section LSP8MetadataBaseURI.

Note that for the tokenId format 3 and 4, the 0x prefix of the tokenId MUST / MUST NOT be added in the final constructed URI because

LSP6 key permissions

We could add a new ERC725Y schema to allow adding keys and their permissions to a ERC725Y key value store:

web3.utils.keccak256('keys')
'0xf29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195'
0xf29790a8 0000000000000000
key:
0xf29790a8 0000000000000000 + address

value:
- keytype: key manager, execution key, execution key - value, execution key - can change store
- contracts to interact with, or all
- functions to call on each contract, or all

0xffffffff + contractaddress + array
^ keytype

permissions:
{
contracts: {
    contract1: [function, function],
    contract2: [function, function]
}
}

[LSP8] Discussion - truncation of `bytes32` tokenId for keyTypes Mapping

To Be Discussed

One of the limitation of the Mapping key type is when dealing with bytes32 tokenIds, such as NFTs.

Since LSP2 defines that a key of type Mapping will truncate on the right side, this can cause collisions if the first 20 bytes of two token IDs are the same. This can be the case when the LSP8 Token ID Type is 3 (string).

Such data keys that are susceptibles to this issue can be the following:

Examples

From the actual LSP8 specs

{
  "name": "LSP8MetadataTokenURI:<address|uint256|bytes32|string>",
  "key": "0x1339e76a390b7b9ec9010000<address|uint256|bytes32|string>",
  "keyType": "Mapping",
  "valueType": "(bytes4,string)",
  "valueContent": "(Bytes4,URI)"
}

Example of a possible LSP8 data key

{
    "name": "WinningBidder:<bytes32-tokenId>",
    "key": "0x2651e040e5e018ae36310000<address>",
    "keyType": "Mapping",
    "valueType": "address",
    "valueContent": "Address"
}

Question

How can a schema be defined that avoids the truncation, and prevent this potential collision?

[LSP7,LSP8] Non-transferable flag

Following @CJ42 comment there, I'm opening this issue to discuss the addition of ERC725Y key-value pairs to flag an asset contract (lsp7 & lsp8 for now) as non-transferable. This addition would be integrated into this PR: PR 682.

Why flagging an asset contract as non-transferable?

For applications to know if you're dealing with NTTs (Non-Transferable Tokens) or not, as it obviously make a big difference. Use-cases linked to NTTs are more associated with certification, and non-financial products, so you might want to display these assets a different way. Also, for a more practical reason, you want the apps & smart cotnracts to know if they can transfer an asset, so they can be adapted.

What keys to add?

I thought about 2 scenarios, one where you would have one key per standard (e.g keccak(LSP7NonTransferable) & keccak(LSP8NonTransferable)). Though, this approach might just add useless complexity. That would mean that we would need to add one key for each new standard and that applications would have to know all these keys.

So the other solution, that in my opinion is better, would be to have a shared Non-Transferable key for all the LSPs. That way, applications would only have to know that key, and no additional key would need to be created if new asset standard are created. The key could be keccak(LSPNonTransferable)

[UP Extension] Add Compatibility for multiple Web3-Extensions

Current Behavior:

The UP Extension does not show up if MetaMask is installed by the user in parallel, as it claims the window.ethereum object for itself first. The object stems from Ethereum as a blockchain client (EVM and its account scheme- used for EOAs or AA controllers in our case.) This allows EVM apps and extensions to easily use the same codebase or even shift projects. In the case of having multiple extensions, it's problematic.

Standard Solution:

The Ethereum object should become more open to other extensions and use cases, letting the users choose their preferred interaction behavior. This has to be discussed with lots of teams and the Web3 space to become adjusted.

Adjusting Object Usage:

There are other solutions, where we can inject the UP extension provider to migrate the significant inconvenience we currently face. They were pointed out by minci#4229 in the LUKSO Discord Dev Channel.
All credit of finding these solutions goes to him.

Short-term

Give the user the option to default to UP or Metamask on all dApp connections (Rabby and Tally wallets do this). They have a switch in the settings where you overwrite the existing provider with the UP provider and vice-versa.

Medium-term

Enable a pop-up to select between conflicting providers (Coinbase wallet does this). When their extension gets installed, they seem to create a map in window.ethereum, where each provider is saved as a key-value pair. Then we could allow the user to select between providers and cache that option to route all future requests to the chosen provider.

Long-term

Propose, adopt, or endorse an interoperable solution like EIP5749's window.evmproviders that will allow all providers not to have to fight for this single space but co-exist and have JavaScript libraries like web3 and ethers to support this multi-wallet provider standard.

Showcase

Screenshot_2022-12-04_at_10 24 19_PM_2

Add Currency Symbol (Ŀ) For Lukso

I would like to propose to add a currency symbol to Lukso that would replace LYX.

Ŀ is the symbol we should use. I initially wanted to use one of the 3 the hexagons in unicode (⬣) but they are rather hard to read on small screens and for near-sighted people so they'll often look like circles at first glance.

Use cases would be same as ETH Ξ, enhancing UI on:
IoT Devices
DApps
Websites
UI/UX
etc...

Unicode U+013F

https://charbase.com/013f-unicode-latin-capital-letter-l-with-middle-dot
https://en.wikipedia.org/wiki/Latin_Extended-A

image

[LSP9] Disallow DELEGATECALL

A LSP9Vault is based on the ERC725X standard but it should not be allowed to use DELEGATECALL.

DELEGATECALL is dangerous and could override the vault storage in unexpected ways, leading to the assets stored under the vault to be overridden or potentially erased.

@frozeman @YamenMerhi @b00ste @skimaharvey

Differentiating between a Deleted Data Key and an Unset Data Key

Currently, we do not differentiate between these two types of Data Keys in the ERC725Y. But maybe there should be a standard way of treating data depending on the type of the Data

Querying any Unset Data Key should return: 0x
Querying a Deleted Data Key should return a specific value based on the previous Data Value of that Data key:

  • bytes - 0x00

  • bytes1 - 0x00

  • bytes2 - 0x0000
    [...]

  • bytes31 - 0x00000000000000000000000000000000000000000000000000000000000000

  • bytes32 - 0x0000000000000000000000000000000000000000000000000000000000000000

  • uint8 - 0x00

  • uint16 - 0x0000
    [...]

  • uint248 - 0x00000000000000000000000000000000000000000000000000000000000000

  • uint256 - 0x0000000000000000000000000000000000000000000000000000000000000000

  • string - 0x00

  • address - 0x0000000000000000000000000000000000000000

  • BitArray - 0x0000000000000000000000000000000000000000000000000000000000000000

  • CompactBytesArray: 0x0000

[LSP0] Improve LSP0 Anti-Phishing by Adding Transfer Delay

Issue Description

LSP0 relies on LSP14 for ownership management, which is beneficial in preventing accidental ownership transfers by mitigating common mistakes such as typos in addresses. However, LSP14 does not provide protection against phishing attacks.

Currently, LSP14 allows attackers to trick users into signing a transferOwnership transaction, which can then be accepted by the attacker as soon as it's mined. This single-step process is vulnerable to phishing attacks.

In contrast, the renounceOwnership process in LSP14 requires two steps and enforces a delay between them. This delay helps reduce the risk of successful phishing attacks since the attacker cannot immediately request the user to sign the subsequent transaction.

Proposed Solution

To enhance the phishing protection in LSP0, we suggest implementing a similar mechanism to the renounceOwnership process for transferOwnership:

After a user initiates a transferOwnership transaction, the recipient address cannot accept ownership until a predefined delay period has passed.
If the new owner does not accept ownership within the limited time window, the transfer is invalidated.
By adding this delay, interfaces can display warnings or notifications to the user regarding the ownership transfer, giving them a chance to rectify any mistakes. Additionally, integration with mobile, email, or SMS services can alert users of ownership transfers, allowing them to take quick action if needed, similar to receiving notifications when someone logs into their Google account.

This proposed solution strengthens LSP0 against phishing attacks, providing a more robust protection mechanism for ownership transfers.

[LSP2] Add `contract` / `Contract` as a valid valueType + valueContent

Proposal

Currently in EVM chains like LUKSO, an address can point to either a smart contract or an Externally Owned Account.
In a LSP2 schema, the address type is used in instances for metadata keys such as:

  • LSP5ReceivedAssets
  • LSP12IssuedAssets

However, in some cases of certain metadata, it might be important to notify strictly that the address MUST BE a smart contract.

Example where contract as value type make sense.

However, an encoding library could ensure that the addresses are actually smart contracts. In the two examples above, this is relevant as a digital has to be a smart contract (for instance, LSP7 or LSP8). In this case, the schema of LSP5 would change as follow.

Before

[
  {
    "name": "LSP5ReceivedAssets[]",
    "key": "0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b",
    "keyType": "Array",
    "valueType": "address",
    "valueContent": "Address"
  },
  {
    "name": "LSP5ReceivedAssetsMap:<address>",
    "key": "0x812c4334633eb816c80d0000<address>",
    "keyType": "Mapping",
    "valueType": "(bytes4,uint128)",
    "valueContent": "(Bytes4,Number)"
  }
]

After

[
  {
    "name": "LSP5ReceivedAssets[]",
    "key": "0x6460ee3c0aac563ccbf76d6e1d07bada78e3a9514e6382b736ed3f478ab7b90b",
    "keyType": "Array",
    "valueType": "contract",
    "valueContent": "Contract"
  },
  {
    "name": "LSP5ReceivedAssetsMap:<contract>",
    "key": "0x812c4334633eb816c80d0000<contract>",
    "keyType": "Mapping",
    "valueType": "(bytes4,uint128)",
    "valueContent": "(Bytes4,Number)"
  }
]

Other cases where address make sense

In other cases, when the specifications want to be loose to allow both either EOAs or Contracts, the address value type can be used. This is the case for instance in LSP6 for AddressPermissions[] can store a list of controllers, where these controllers can be either EOAs or smart contracts.

Additional infos

Libraries like erc725.js could check when encoding at runtime that the address being encoded is actually a smart contract, and for instance fail if it is not.

Such thing could be bypassed, by setting data keys / value pairs manually without such library, but still the library could discard entries that are not a contract from large arrays being read from the ERC725Y storage.

[LSP8] Add explanation of hashed tokenId

Overview

LSP8 requires to set an explanation of what tokenId content means. The explanation is currently documented to be an integer of key LSP8TokenIdType:

  • 1: address another contract
  • 2: uint256 a number, which may be an incrementing count where each minted token is assigned the next number
  • 3: bytes32 a hashed value (ie. serial number)

Problem

In a case of 3 when tokenId represents a hashed value, dapps and other contracts may need to be able to retrieve actual value (prior to it's been hashed).

Improvement Proposal

LSP8TokenIdHashFunction

Explains a hashing function applied to generate a tokenId.

{
    "name": "LSP8TokenIdHashFunction",
    "key": "0x200d7fc10771371795cceb6ad6d33d5959c47250486fb93f77f0c20088b90a97",
    "keyType": "Singleton",
    "valueType": "string",
    "valueContent": "String"
}

possible values:

  • keccak256(bytes)

LSP8TokenIdValue:TokenId

Contains a value that's hashed to generate a tokenId.

{
    "name": "LSP8TokenIdValue:<bytes32>",
    "key": "0x60fcfd25909da10abc320000<bytes32>",
    "keyType": "Singleton",
    "valueType": "bytes",
    "valueContent": "Bytes"
}

If value is a string, it must be encoded in utf8 and read as Web3.utils.hexToUtf8(hexValue)

Improve `avatar` field in LSP-3

Add also game engines.
and platform.

     "avatar": [ // a 3D file avatar mostly in FBX and/or OBJ format, multiple file formats of an avatar can be added
            {
                "hashFunction": ['keccak256(json)','md5(bytes)'],
                "hash": ['string','string'],
                "url": ['string', 'string'],
                "fileType": ['manifest','assetbundle'],
                "engine": 'unity',
                "platform": "unix",
                "version": 1.23.1
            }
        ]

[LSP6] Add `REENTRANCYBOOLEAN` to AllowedCalls

Withexecute(...):

All reentrant calls will happen in the context of a call so in order to be successful contracts with REENTRANT permission will also need to have some AllowedCalls permissions.

if a contract has:

  • REENTRANT permission
  • list of multiple allowed calls (one call that will mint and another one that will approve for example)

At the moment I cannot limit the reentrancy to a specific call (for example approve call).

WithexecuteRelayCall(...):

If a signer has the reentrancy permission. All his signed payload could possibly be used in a reentrancy context. However With the below solution we can also limit it to signer + specific allowed calls

Solution

I think we could modify our allowed call standard and append it by 1 byte related to Reantrancy.

The new standard could be:
Standard:Address:Function:ReentrancyBool

Implementation

When verifying AllowedCalls, since we know whether the call is a reentrant call, we can add a bool isReentrantCallparameters to _verifyAllowedCall(...) and check if this particular call is allowed as a reentrant call.

        function _verifyAllowedCall(..., bool isReentrantCall) internal view {
        ...
        bool isAllowedReentrant = true;

        for (uint256 ii = 0; ii < allowedCallsLength; ii += 30) {

            bytes memory chunk = BytesLib.slice(allowedCalls, ii + 1, 29);
            ...
            //if isReentrantCall is true, we check that the last byte value is FF
            if(isReentrantCall && bytes1(bytes29(chunk) << 224) != 0xFF) {
                isAllowedReentrant = false;
            }

            if (isAllowedStandard && isAllowedAddress && isAllowedFunction && isAllowedReentrant) return;
        }

        revert NotAllowedCall(from, to, selector);
    }

[LSP2] CompactBytesArray - complete technical overview with examples

This issue is aimed at having a complete technical low-level overview of CompactBytesArray type with examples which combined should cover CompactBytesArray completely. LSP2 must have all valueTypes described and covered the same way Solidity documentation has covered its data types and respective ABI encoding/decoding.


TL;DR

Not enough documentation on how to encode/decode [CompactBytesArray]. We have explanations for bytes[CompactBytesArray] and bytesN[CompactBytesArray] in LSP2, but in LSP6 we use (bytes4,address,bytes4)[CompactBytesArray] and both the type and the encoding don't match what is described in LSP2.


The issue

Currently (06.02.2023) in LSP2 we have bytes[CompactBytesArray] and bytesN[CompactBytesArray] value types. These are covered and well understood. But that documentation comes short of the explanation required with the introduction of LSP6's AllowedCalls. Both of these were released with v0.8.0 see CHANGELOG8.pdf

LSP6's AllowedCalls scheme uses valueType set as (bytes4,address,bytes4)[CompactBytesArray], and it has the custom case of encoding [CompactBytesArray] of tuples described in LSP6 (not the right place, IMO). This custom case, first of all, must not be custom and it must be covered by LSP2, and it's not.

On top of that, since we have (bytes4,address,bytes4)[CompactBytesArray] in LSP6 and it doesn't match bytes[CompactBytesArray] and bytesN[CompactBytesArray] it implicitly allows developers to use any other type with [CompactBytesArray], like address[CompactBytesArray][CompactBytesArray] (2D CompactBytesArray). And the question is - how will it be encoded? There is no single source of truth that everyone can refer to at the moment to implement the correct encoding/decoding functions of CBAs.

LSP2 is a standard. We must define low-level specifications that others will build upon their custom structures the same way we use Solidity and its specifications to encode and decode ABI of types it provides. These custom structures will use a specific, known and well-documented set of small blocks (value types) and everyone will be able to refer to LSP2 instead to understand how to create and disassemble these small blocks (encode and decode ABI).


Additional question: if the compact bytes array has 2 or more levels of nested types do we compact only the first layer or all of them? My answer is - only the first layer, the type declared directly next to the left side of the [CompactBytesArray].

Example: (address[],(boolean,bytes4))[CompactBytesArray] (a type that doesn't make sense but is technically possible).

Do we encode ...,(boolean,bytes4)... tuple the default way or do we reduce/compact it as well?

My understanding is that we encode it the default way. The same applies in my opinion to the question above about arrays in CompactBytesArray.

Encoding example of (address[],(boolean,bytes4))[CompactBytesArray]:

// The `(address[],...)` part of `(address[],(boolean,bytes4))[CompactBytesArray]`
web3.eth.abi.encodeParameter('address[]', ['0x98d2fF3907A4a9dEb10B1F2F79EBF078984501BF'])
=>
0x0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000001
00000000000000000000000098d2ff3907a4a9deb10b1f2f79ebf078984501bf

// The `(...,(boolean,bytes4))` part of `(address[],(boolean,bytes4))[CompactBytesArray]`
web3.eth.abi.encodeParameter('(bool,bytes4)', [true, '0xffbbffbb'])
=>
0x0000000000000000000000000000000000000000000000000000000000000001
ffbbffbb00000000000000000000000000000000000000000000000000000000

// And instead of encoding these values as default array (with the total count of bytes = 256):
web3.eth.abi.encodeParameter('(address[],(bool,bytes4))[]', [[['0x98d2fF3907A4a9dEb10B1F2F79EBF078984501BF'], [true, '0xffbbffbb']]])
=>
0x0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000001
ffbbffbb00000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000001
00000000000000000000000098d2ff3907a4a9deb10b1f2f79ebf078984501bf

// We will encode these values as CompactBytesArray (with the total count of bytes = 196).
// Note: erc725js.encodeParameter is not a real function! Used just for explanation.
erc725js.encodeParameter('(address[],(bool,bytes4))[CompactBytesArray]', [[['0x98d2fF3907A4a9dEb10B1F2F79EBF078984501BF'], [true, '0xffbbffbb']]])
=>
00C0
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000001
ffbbffbb00000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000001
00000000000000000000000098d2ff3907a4a9deb10b1f2f79ebf078984501bf

After a discussion with @b00ste on Friday (04.02.2023) it also came to mind that [CompactBytesArray] could completely replace []. Any thoughts on that idea are welcome.

But [CompactBytesArray] has two downsides in comparison to [] one of which can be fixed:

  • (fixable) no way to declare fixed size [CompactBytesArray]. For the default array type, you can place a number between square brackets to define the array's size, e.g. [2]. As a solution it could be placed separated by a colon [CompactBytesArray:2];
  • (non-fixable*) just having the ABI of [CompactBytesArray] you have no way to tell if it's valid or not. The ABI of [] (as of any other Solidity type) must have the number of bytes be a multiple of 32. One byte off and it's not valid. This is not the case with [CompactBytesArray] and cannot be.
    * if the solution mentioned below for the fixed-size CBAs will be applied there is a certain set of conditions that will allow us to produce a type that can be validated before the encoding attempt has happened. The set of conditions is: (1) all subtypes have fixed size and (2) CBA is itself fix-sized.
    Example: the expected bytes count for bytes8[CompactBytesArray:10] is (8 bytes + 2 bytes size prefix) * 10 = 100 bytes.

[LSP2] Tuple encoding

We have the following tuple examples in the LSP2 standard:

Screenshot 2023-03-06 at 10 47 49

Screenshot 2023-03-06 at 10 45 12

These examples are valid and work both ways - encoding and decoding.
But using tuples like (address,bytes,string) or (bytes,bytes,bytes8) or anything where we have a dynamic type in any but the last position will not work because values are just "glued together".

And even though we can make this (bytes,bytes8) work by taking last 8 bytes as bytes8 and the rest as bytes it doesn't make sense when it comes to implementation of deocding.

Example:

type = (bytes,string)
values1 = (0xcafe,"not really a cafe, is it?")
values2 = (0xbeeeeeeeeeeeeeef,"some people just love it")

... doing encoding ...

values1Encoded = 0xcafe6e6f74207265616c6c79206120636166652c2069732069743f
values2Encoded = 0xbeeeeeeeeeeeeeef736f6d652070656f706c65206a757374206c6f7665206974

/// ERROR: where in these long blobs the first values start and the second end?
decodeLsp2Values(type, values1Encoded)
decodeLsp2Values(type, values2Encoded)

I suggest we either fallback to using Solidity's way of encoding tuples or add the same 2 bytes for the length of each value (as we have in the CBAs) in the tuple, or even better we use the following idea suggested by @skimaharvey: #172 (comment)

The idea is to have 1 byte that will hold the length of the length of the element, the next 1 or more bytes that describe the length of the element and the next 1 or more bytes should be the element itself:

Screenshot 2023-03-06 at 11 07 10

Using that idea tuples will be encoded in the following manner:

type = (bytes,string)
values1 = (0xcafe,"not really a cafe, is it?")
values2 = (0xbeeeeeeeeeeeeeef,"some people just love it")

... doing encoding ...

values1Encoded = 0x01 02 cafe 01 19 6e6f74207265616c6c79206120636166652c2069732069743f
values2Encoded = 0x01 08 beeeeeeeeeeeeeef 01 18 736f6d652070656f706c65206a757374206c6f7665206974

/// No errors as we know the length! 
/// And it only takes in most cases `2 * tuple.countOfNestedTypes` bytes more per 1 tuple
/// Where `countOfNestedTypes` is the number of types you declare within parentheses `()`.
decodeLsp2Values(type, values1Encoded)
decodeLsp2Values(type, values2Encoded)

[LSP25] Execute Relay Call as its own standard (extracted from LSP6)

Overview

Currently, the 3 x functions getNonce, executeRelayCall and executeRelayCallBatch are part of the LSP6 interface and embedded in the standard.

However, meta transactions in web3 are used in many different context, such as:

  • voting (ask a 3rd party to cast your vote on your behalf, paying the gas for the transaction). See Uniswap example, or proxy voting in real life: https://en.m.wikipedia.org/wiki/Proxy_voting#:~:text=Proxy voting is a form,enable a vote in absence.
  • NFT Marketplaces that want to be built to accept meta transactions natively, without having to put a Key Manager in front.
  • People wanting to build decentralised relayers
  • Free NFTs with free mintings, given as gifts (e.g: Stickmen Toys: https://stickmentoys.com/, or Warners Records UK that gave free musical NFTs). If you want to give NFTs for free, you can make the NFT to not have a price (free), but the transaction will always incurs a gas cost. Meta transaction can enable that.
  • Any services that require a lot of transactions (streaming, microtransactions, gaming, defi, etc…)

By putting Meta Transaction in its own standard as a mew LSP, this offer a new separate small building block / component that devs can use to embed meta transactions in their own protocol / applications (instead to have to also opt for permissions management, which is not necessarely related and that they might not want).

Questions

Should LSP25 be a MUST in LSP6?

The question would be if:

  • LSP25 is also part of LSP6 ➕ (as a COULD, like LSP20 is)
  • LSP25 is not part of LSP6 ➖, and our LSP6KeyManager is simply an implementation contract built in to include also LSP20 + LSP25 so that it can be specifically used in front of a Universal Profile.

So far, while discussing on Monday with @frozeman, we mentioned that the specs of LSP6 have to specify that it MUST includes the LSP25 standard + properly described with a short list of functions.

⚠️ BREAKING CHANGE --> What would be the new version for signing an execute relay call?

So far for executeRelayCall, executors submit transactions signed. The data to sign for a valid executeRelayCall has to be formatted according to the following format (currently defined in LSP6 specs).

image

Since we are now moving this to its own standard, I am wondering what should be the new 4th parameter LSP6_VERSION = 6.

option 1) Shouldn't this be changed to LSP25_VERSION = 25 as a result?
option 2) Or should this be kept as it is? The version is specific to the contract implementing the standard, like in this case LSP6?

On my side, I don't see a strong reason for option 2), but instead would favour option 1 to have the same approach as EIP191 but for different versions.
This way, contracts could keep the same LSP25 interface, but create different LSP standards for different signed data schemes (see screenshot below for EIP191)

--> Important to be discussed

https://eips.ethereum.org/EIPS/eip-191

image

Technical references

These would be the changes in the interface of LSP6 + the standard interface of LSP25. (we take out these 3 functions out of LSP6 essentially).

Interface of LSP6

target()
execute()
executeBatch()

+ PermissionsVerified event

Interface of LSP25

getNonce()
executeRelayCall()
executeRelayCallBatch()

Remove `JSONURL` and only use `AssetURL`?

We could remove JSONURL and only have AssetURL, as the verification function tells you how to verify the hash.

We could then use a compact array to determine the length of verification funcition, verification data and source url.
e.g.

verification function + verification data (e.g. hash) + url

ERC725.js

Lets create

https://github.com/lukso-network/LIPs/blob/master/LSPs/LSP-2-ERC725YJSONSchema.md

let provider = web3 || graphQlApollo;

let universalprofile = new ERC725(ERC725YJsonSchema, address, provider);

universalprofile.getData('LSP2IssuedAssets[]')
> ['0x1234567...', '0x2345678...']

universalprofile.getData('LSPXassetURI')
> {
    hashFunction: 'keccak256',
    hash: '0x23456789...',
    uri: 'ipfs://Q3456789..'
}

universalprofile.getData('LSPXjsonURI')
> {
    myCustomJsonContent: '123456789',
    otherCoolProp: 'Wow'
} // this json hash has been verified

universalprofile.getData('LSP2Name')
> 'My Cool name'
// as web3.js module

new web3.eth.Contract;
new web3.eth.ERC725;


// for execution in a wallet


web3.eth.accounts.wallet.newERC725('0xprivateKey', '0x725ffffffffff...')


web3.eth.accounts.wallet[1]
> {
    type: 'erc725',
    address: '0x725ffffffffff...', // comes from the user ^
    keyManager: '0x234567', // comes from the erc725Account.owner
    keyAddress: '0x08765432', // comes from 0xprivateKey
    privateKey: '0xprivateKey'
}

// usage
web3.eth.sendTransaction({
    from: '0x725ffffffffff...',
    to: '0xff123...',
    value: '100000000000',
    gasLimit: 60000
})

myWeb3Contract.methods.coolFunction(coolParam).send({
    from: '0x725ffffffffff...',
    gasLimit: 200000
})

[LSP11] SocialRecovery Improvement

LSP11SocialRecovery Improvement

I would like to open a discussion on the LSP11 standard, which serves as a social recovery mechanism for users to regain access to their Smart Contracts. While this standard is fully functional, there are several aspects I believe could be improved upon to facilitate better adoption and integration with other LSPs.

Critiques

  • Lack of Interoperability: The current design of LSP11 fits primarily with an LSP0 owned by an LSPP6. The recovery mechanism functions through a voting system conducted by guardians, and once the secret word is provided in the recoverOwnership(..) function, the LSP11 contract sets LSP6 permissions on the LSP0 for the address voted for.

    This design limits the flexibility of the system and reduces the opportunities for interoperability. Particularly considering the recent integration of LSP20 within the LSP0, where the interaction with LSP0 became owner agnostic, we should aim to design the social recovery system in an owner-agnostic manner too.

    Ideally, the social recovery system should function irrespective of the owner and the contract type, potentially not limited to an LSP0. The person elected for recovery should be able to either set LSP6 permissions on the account post-recovery, transfer ownership, set LSPXXX permissions, or maybe even execute another function.

    In this way, the vote can happen based on a calldata to execute, or a hash of the calldata.

  • Deployment Costs: As a standard potentially useful to a wide range of users, ideally each account-contract should have an LSP11. However, the current requirement to deploy a unique contract for each account—even when using proxies—could create a significant cost barrier for companies aiming to provide social recovery options to their users.

    To overcome this, we should consider redesigning the standard in a way that enables a single instance of the standard to serve as a singleton. In such a design, a single instance of the social recovery contract could serve multiple users with differing guardian settings, thresholds, and configurations according to the linked contract.

    This approach would significantly reduce deployment costs and increase user adoption. If necessary, individuals who desire a unique contract can deploy a separate instance specific to their requirements, preventing the instance from being used with other accounts than the ones they specify.

Ideas and Concerns

  • Delays: Should there be a time range for a social recovery process that invalidates the votes of all previous guardians? Should it be part of the standard or left optional to be implemented without breaking the function specification ?

  • Privacy: Some of the social recovery contracts, emphasize on privacy where an account can set guardians but without revealing their addresses, in this case, the account will set a hash of the addresses, and when recovering the guardians are allowed based on their hash of addresses. This could be helpful for privacy of accounts (UniversalProfile)

  • Secret Word Leak: Since the standard use the secret word to recover access to the contract (either alone or with guardians), there is the possibility of having two people at the same time use the same hash, and one can reveal the plain secret before the other making the other vulnerable to be "hacked" by his guardians. Several ideas are being proposed such as double hashing, registry checking for a duplicate hash, etc .. This needs more research and opinions.

  • Accepting Guardian invitation: Many social recovery contracts implement the invitation mechanism, where first you invite a guardian and he should accept the invitation. I don't see the reason for implementing this mechanism, as it adds additional cost for the guardian to accept the invitation. As well, some of the contracts to be set as guardians maybe cannot execute until a certain condition is met.

  • Relay Execution: While it's true that providing functions that work on signed messages is good and makes the execution of a recovery frictionless, it may result in undesired action as a user can be tricked to sign a message and have this message not exposed can be executed later. This might go against the idea that the main account should have the ability of relay execution, not the targets contract. As well, in this way we need to integrate EIP-1271 as we should expect the use of smart contract accounts as guardians. To be discussed.

  • Cancel the recovery process: Making the account able to cancel a recovery process.

I can see the features listed above as 'standard', other custom features such as recovering based on specific logic can be implemented on top of the LSP11SocialRecovery contract. For example, a contract that works with Custom logic X for recovering can be added as a guardian for the main LSP11SocialRecovery contract.

While I see that these are lots of ideas and improvements, I don't see a reason to not implement these ideas together If they make sense, instead of standardizing several social recovery contracts with different features and interfaces which will not contribute to the Interoperability.

[LSP24] Multichain Address Resolution

Proposing a standard related to Multichain Address Resolution to start by querying the storage of an ERC725Y contract. The resolution can happen to the ERC725Y contract itself, or other addresses. Verification of the resolution will be based on the ERC725Y contract on both chains, by making the ERC725Y contracts point to each other

To have a background of how the resolution happens with ENS: https://eips.ethereum.org/EIPS/eip-2304

Feedback about the logic of the standard is welcomed (not typo/grammatical/vocab error as this is not a PR) 🤝


lip: ?
title: Multichain Address Resolution
author: [Your Name] <[Your Email]>
discussions-to:
status: Draft
type: LSP
created: 2023-06-19
requires: ERC725Y, LSP2

Simple Summary

This standard describes a set of ERC725Y data key-value pairs that allow resolution of addresses on different chains, and a mechanism for verifying the claim of address resolution.

Abstract

The LSP24MultichainAddressResolution data key will allow resolution of addresses on other chains based on an address or a standard hash.

Motivation

For EVM chains, if an address is an Externally Owned Account (EOA) it is known that the controller of this EOA can control it across different chains. But for smart contracts it's different, even with having contracts at the same address across different chains, it's possible to have different contracts, which makes having a contract at same address on different chains does not guarantee that these contracts are the same.

It is essential to have a mechanism that resolve an address from a chain to another one, making it possible to resolve contract addresses to their equivalents on other EVM chains, and normal addresses to other chains, even non EVM ones such as Bitcoin, Ripple, Solana, etc..

Specification

Address Resolution

Every contract that supports the LSP24MultichainAddressResolution standard MUST have the following data key:

LSP24MultichainAddressResolution

{
     "name": "LSP24MultichainAddressResolution:<bytes4>:<address|bytes32>",
     "key": "0x049b19b87a61<bytes4>00<address>",
     "keyType": "MappingWithGrouping",
     "valueType": "bytes",
     "valueContent": "Address|Bytes"
}
  • The data key is constructed from 2 dynamic parts:

    • The first dynamic part is bytes4 which represent the chain of the address resolved
    • The second dynamic part is either the address to lookup on another chain or a bytes32 hash of a specific standard.
  • The data value stored under this data key is the address in the native format of the network of the address resolved. Each network could have a different representation of the address encoding, for example, bitcoin address encoding is different than EVM address encoding.

The bytes4 chain representation and its respective address encoding can be found and added to the table at the end of the specification. For example:

Network Bytes4 representation Address Encoding
LUKSO TBD ChecksummedHex
Ethereum TBD ChecksummedHex
Bitcoin TBD P2PKH(0x00), P2SH(0x05), SegWit(‘bc’)
... ... ...

Example 1

Suppose an ERC725Y contract deployed on LUKSO Mainnet, and we want to resolve its corresponding address on Ethereum Mainnet. Here's how we would proceed:

  1. We start by identifying the bytes4 representation of the Ethereum Mainnet chain, let's say for instance, it's 0xffffffff.

  2. Next, we need the address of the ERC725Y contract on LUKSO Mainnet. In our example, let's consider it to be 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.

  3. Using the above details, we can construct the data key as follows: 0x049b19b87a61ffffffff00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.

After retrieving the data stored under this key, let's say we got 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb. This implies that the ERC725Y contract's address on LUKSO Mainnet is 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, and the corresponding address of this contract on the Ethereum Mainnet is 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.

Example 2

There could be the case where a lookup is needed for a specific standardized wallet, for example a wallet standardized under the name of XYZ50:

  1. We start by identifying the bytes4 representation of the chain to lookup, let's say for instance, it's 0xffffffff.

  2. Next, we need the hash standardized for the wallet. In our example, it can be standardized as the keccak256 of XYZ50 equal to 0x1e647dad4813ed23203d95b2d3ab27ea25a4c1a2ed45c3002dc063fe9f4a14a4

  3. Using the above details, we can construct the data key as follows: 0x049b19b87a61ffffffff001e647dad4813ed23203d95b2d3ab27ea25a4c1a2.

After retrieving the data stored under this key, let's say we got 0xcccccccccccccccccccccccccccccccccccccccc. This implies that the wallet XYZ50 on the chain looked up is at the address 0xcccccccccccccccccccccccccccccccccccccccc.

Example 3

There could be the case where a lookup is needed for an address on a non EVM chain such as Bitocin. Here's how we would proceed:

  1. We start by identifying the bytes4 representation of the chain to lookup, let's say for instance, it's Bitcoin and its chain representation is 0xbbbbbbbb.

  2. Next, we need the address to lookup. In our example, let's consider it to be 0x2222222222222222222222222222222222222222.

  3. Using the above details, we can construct the data key as follows: 0x049b19b87a61bbbbbbbb002222222222222222222222222222222222222222.

After retrieving the data stored under this key, let's say we got 0x0062e907b15cbf27d5425399ebf6f0fb50ebb88f18. Given that the encoding of Bitcoin addresses is based on P2PKH (base58check), after decoding the address resolved will be 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.

Verifying Address Resolution

While it's relatively simple to claim that a certain address on another chain is the corresponding address or under the same control, this can potentially lead to deceptive assertions, causing major problems. Therefore, it's essential to have a standardized mechanism for verifying such address resolution claims.

For verification purposes, the ERC725Y contract should exist on the chain to lookup. To verify that the resolution is correct, it is essential to have the same reverse lookup happen on the lookup chain. In this way, we have a resolution that could go in both ways, making it possible and sure that these 2 contracts are under the same control and point to each other.

This method represents an autonomous way for verifying the claim of address resolution, but other solutions such as verifying signature on the address looked up could also be used.

Example 4

Continuing with the example 1, the ERC725Y contract on the Ethereum chain at address 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb should store a data key pointing back to the LUKSO network.

Supposing the bytes4 representation of LUKSO Mainnet is 0x42424242, the data key 0x049b19b87a614242424200bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb should exist in the ERC725Y contract on the Ethereum Mainnet , and the data value stored under the data key should be equal to 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.

Example 5

In case where the lookup is not intended for the ERC725Y contract itself, the verification process will require few more steps.

If the lookup in the ERC725Y contract deployed on LUKSO Mainnet is for a vault address to be checked on Ethereum Mainnet, then the lookup start with:

  1. We start by identifying the bytes4 representation of the Ethereum Mainnet chain, let's say for instance, it's 0xffffffff.

  2. Next, we need the address of the vault contract on LUKSO Mainnet. In our example, let's consider it to be 0xdddddddddddddddddddddddddddddddddddddddd.

  3. Using the above details, we can construct the data key as follows: 0x049b19b87a61ffffffff00dddddddddddddddddddddddddddddddddddddddd.

After retrieving the data stored under this key, let's say we got 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee. This implies that the vault contract's address on LUKSO Mainnet is 0xdddddddddddddddddddddddddddddddddddddddd, and the corresponding address of this contract on the Ethereum Mainnet is 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.

The verification phase cannot go directly to 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee as this contract could be not implementing ERC725Y and just representing a vault. To have a verified resolution, we need a reverse lookup using the ERC725Y contract.

The ERC725Y should be available on the chain to lookup, in our case Ethereum Mainnet, and should be resolved from LUKSO Mainnet and should be pointing back to the LUKSO address on Ethereum Mainnet as shown in Example 4.

After verfying that the ERC725Y contracts on Ethereum and LUKSO point to each other, the verification to the vault happens as follows:

  1. We start by identifying the bytes4 representation of the LUKSO Mainnet chain, let's say for instance, it's 0x42424242.

  2. Next, we need the address of the vault contract on Ethereum Mainnet. In our example above, we got it as 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.

  3. Using the above details, we can construct the data key as follows: 0x049b19b87a614242424200eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.

The data stored under this data key should be equal to 0xdddddddddddddddddddddddddddddddddddddddd. This implies that the vault contracts on LUKSO Mainnet and Ethereum Mainnet are pointing and referencing each other through the ERC725Y contract existing on both chains.

In this way, a resolution that could go in both ways is established, making it possible to verify that these two contracts are under the same control and point to each other.

Rationale

The process of verification of address resolution autonomously may only be available for specific networks. Some networks do not have the capability to support contracts or storage, thus address resolution can be implemented, but not verification.

The standard does not enforce the process of creating the bytes4 representation of the chain. It is up to each chain to standardize their bytes4 representation. This approach can support a significant number of chains, up to 4,294,967,295.

The decision not to make the bytes4 as the chainId representation is because some networks have chainId that are larger than 4 bytes. Additionally, choosing not to use the hash of the network name or currency is due to the potential hash collisions.

Therefore, it's essential for each chain to add their representation to LSP24, while reviewing the already used bytes4 chain representations.

Implementation

ERC725Y JSON Schema LSP24MultichainAddressResolution:

[
    {
        "name": "LSP24MultichainAddressResolution:<bytes4>:<address|bytes32>",
        "key": "0x049b19b87a61<bytes4>00<address>",
        "keyType": "MappingWithGrouping",
        "valueType": "bytes",
        "valueContent": "Address|Bytes"
    }
]

List of Chains and Encoding

Chains can be added here:

Network Bytes4 representation Address Encoding
LUKSO TBD ChecksummedHex
Ethereum TBD ChecksummedHex
Bitcoin TBD P2PKH(0x00), P2SH(0x05), SegWit(‘bc’)
... ... ...
... ... ...

Copyright

Copyright and related rights waived via CC0.

Icon Request: icon-lyx

Would like to to propose an official currency symbol to Lukso that would act as a shortened version for LYX.

this is the symbol we should use.

I think the Latin Extended A works rather well (we've went ahead and used it in https://wandz.works/orderbooks, as repeating LYX too much all over the website was cluttering the pages)

Use cases would be same as ETH Ξ :

  • IoT
  • DApps
  • Websites
  • UI/UX

Build on <i class="fa fa-lyx" aria-hidden="true"></i>

Icon:
image

Unicode U+23E3, HTML entity code &#9187

Final Poll is here on X: https://x.com/DWOPEs/status/1803086212455936460?t=tJXqtJZZHIDB_Qiija6IEg&s=19

LSP3IssuedAssets[] uses valueContent instead of elementValueContent

The current JSON schema for LSP3IssuedAssets[] source seems wrong: valueContent is used instead of elementValueContent (same issue for type).

{
    "name": "LSP3IssuedAssets[]",
    "key": "0x3a47ab5bd3a594c3a8995f8fa58d0876c96819ca4516bd76100c92462f2f9dc0",
    "keyType": "Array",
    "valueContent": "Address",
    "valueType": "address"
}

I believe it should look similar to LSP4Creators[] instead:

{
    "name": "LSP4Creators[]",
    "key": "0x114bd03b3a46d48759680d81ebb2b414fda7d030a7105a851867accf1c2352e7",
    "keyType": "Array",
    "valueContent": "Number",
    "valueType": "uint256",
    "elementValueContent": "Address",
    "elementValueType": "address"
}

Suggested changes:

{
    "name": "LSP3IssuedAssets[]",
    "key": "0x3a47ab5bd3a594c3a8995f8fa58d0876c96819ca4516bd76100c92462f2f9dc0",
    "keyType": "Array",
    "valueContent": "Number",
    "valueType": "uint256",
    "elementValueContent": "Address",
    "elementValueType": "address"
}

The above example is also used in the ERC725YJSONSchema Array definition; I think it should be updated accordingly.

I will open a PR with a fix

[LSP9] Should we add ERC1271 to verify signatures at the vault

Adding ERC1271 isValidSignature() to an LSP9 vault would allow for login with a vault. Then vault would then call the isValidSignature() on the owner, to see if the signature can be verified by one of the SIGN keys controlling the UP/ower contract.

currently LSP9 does not have ERC1271, as any app can always detect the owner and call isValidSignature() on the owner himself.

[LSP0] Should the fallback function call into the owner?

As a discussion for later.
Should the fallback function call into the owner?

        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()) }
            }
        }

[LSP4] Add Background image field to LSP4 JSON Metadata

As reported by @jakeprins , LSP3 Profile contains two fields for profile image and background image.

image

However LSP4 JSON metadata contains only 1 field images, and not a separate field for background image.

image

Should we consider adding the background image field for LSP4 JSON Metadata as well?

Consideration: how should we name the fields then if we introduce both fields in LSP4? Can we also use the term "profileImage" for LSP4?

Add gas limit to calls of a controller with only SUPER_TRANSFERVALUE permission

In the rare event some contracts have code within their receive()/fallback() functions, SUPER_TRANSFERVALUE could be used to initiate calls from these fonctions.

One way to prevent it could be by limiting the gas of a transfer made by controller that has the SUPER_TRANSFERVALUE permission does not have the required CALL/SUPER_CALL permission.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.