From fc78894753e2f24dd167a8e90401b56b1af938f8 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 11 Jul 2022 13:39:05 +0200 Subject: [PATCH 1/6] add setData function to NFT --- src/tokens/NFT.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/tokens/NFT.ts b/src/tokens/NFT.ts index 7fd2b4b1..adeea7a6 100644 --- a/src/tokens/NFT.ts +++ b/src/tokens/NFT.ts @@ -1159,6 +1159,38 @@ export class Nft { return trxReceipt } + /** setData + * This function allows to store data with a preset key (keccak256(ERC20Address)) into NFT 725 Store + * only ERC20Deployer can succeed + * @param nftAddress erc721 contract adress + * @param address user adress + * @param key Key of the data to be stored into 725Y standard + * @param value Data to be stored into 725Y standard + * @return {Promise} transactionId + */ + public async setData( + nftAddress: string, + address: string, + key: string, + value: string + ): Promise { + const dtContract = setContractDefaults( + new this.web3.eth.Contract(this.nftAbi, nftAddress), + this.config + ) + + const estGas = await estimateGas(address, dtContract.methods.setNewData, key, value) + + // Call setData function of the contract + const trxReceipt = await dtContract.methods.setNewData(key, value).send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) + + return trxReceipt + } + /** Get Owner * @param {String} nftAddress erc721 contract adress * @return {Promise} string From 6493688ae5f9bb1d8331b41f02075402ba1c8e09 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 11 Jul 2022 23:26:31 +0200 Subject: [PATCH 2/6] check nft permisions on setData() --- src/tokens/NFT.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tokens/NFT.ts b/src/tokens/NFT.ts index adeea7a6..3de08ec2 100644 --- a/src/tokens/NFT.ts +++ b/src/tokens/NFT.ts @@ -1174,15 +1174,19 @@ export class Nft { key: string, value: string ): Promise { - const dtContract = setContractDefaults( + if ((await this.getNftPermissions(nftAddress, address)).store !== true) { + throw new Error(`User is not ERC20 store updater`) + } + + const nftContract = setContractDefaults( new this.web3.eth.Contract(this.nftAbi, nftAddress), this.config ) - const estGas = await estimateGas(address, dtContract.methods.setNewData, key, value) + const estGas = await estimateGas(address, nftContract.methods.setNewData, key, value) // Call setData function of the contract - const trxReceipt = await dtContract.methods.setNewData(key, value).send({ + const trxReceipt = await nftContract.methods.setNewData(key, value).send({ from: address, gas: estGas + 1, gasPrice: await getFairGasPrice(this.web3, this.config) From 436e873833977a4b1493bcd9a1f552a50559bb98 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 11 Jul 2022 23:36:09 +0200 Subject: [PATCH 3/6] use keccak256 and asciiToHex for key and value --- src/tokens/NFT.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/tokens/NFT.ts b/src/tokens/NFT.ts index 3de08ec2..5f97fb40 100644 --- a/src/tokens/NFT.ts +++ b/src/tokens/NFT.ts @@ -1183,10 +1183,18 @@ export class Nft { this.config ) - const estGas = await estimateGas(address, nftContract.methods.setNewData, key, value) + const keyHash = this.web3.utils.keccak256(key) + const valueHex = this.web3.utils.asciiToHex(value) + + const estGas = await estimateGas( + address, + nftContract.methods.setNewData, + keyHash, + valueHex + ) // Call setData function of the contract - const trxReceipt = await nftContract.methods.setNewData(key, value).send({ + const trxReceipt = await nftContract.methods.setNewData(keyHash, valueHex).send({ from: address, gas: estGas + 1, gasPrice: await getFairGasPrice(this.web3, this.config) @@ -1258,8 +1266,9 @@ export class Nft { new this.web3.eth.Contract(this.nftAbi, nftAddress), this.config ) - const data = await nftContract.methods.getData(key).call() - return data + const keyHash = this.web3.utils.keccak256(key) + const data = await nftContract.methods.getData(keyHash).call() + return data ? this.web3.utils.hexToAscii(data) : null } /** Gets data at a given `key` From 215ddf43dfaec9c0bc98b8c8f37d3f67fe7c32e9 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 11 Jul 2022 23:36:20 +0200 Subject: [PATCH 4/6] test setData() --- test/unit/tokens/Nft.test.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/unit/tokens/Nft.test.ts b/test/unit/tokens/Nft.test.ts index 4fd1b9ec..57dc6c46 100644 --- a/test/unit/tokens/Nft.test.ts +++ b/test/unit/tokens/Nft.test.ts @@ -433,4 +433,31 @@ describe('NFT', () => { assert(metadata[0] === metadataAndTokenURI.metaDataDecryptorUrl) assert(metadata[1] === metadataAndTokenURI.metaDataDecryptorAddress) }) + + it('#setData - should FAIL to set a value into 725Y standard, if Caller has NOT store updater permission', async () => { + const key = 'KEY' + const data = 'NewData' + assert((await nftDatatoken.getNftPermissions(nftAddress, user1)).store === false) + + try { + await nftDatatoken.setData(nftAddress, user1, key, data) + assert(false) + } catch (e) { + assert(e.message === 'User is not ERC20 store updater') + } + assert((await nftDatatoken.getData(nftAddress, key)) === null) + }) + + it('#setData - should set a value into 725Y standard, if Caller has store updater permission', async () => { + const key = 'KEY' + const data = 'NewData' + + // add store updater permission + await nftDatatoken.addStoreUpdater(nftAddress, user1, user1) + assert((await nftDatatoken.getNftPermissions(nftAddress, user1)).store === true) + + await nftDatatoken.setData(nftAddress, user1, key, data) + + assert((await nftDatatoken.getData(nftAddress, key)) === data) + }) }) From 09d334123904d99c9674d7bf3353dfde5beb3628 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 11 Jul 2022 23:43:43 +0200 Subject: [PATCH 5/6] use asciiToHex in datatoken.setData() --- src/tokens/Datatoken.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tokens/Datatoken.ts b/src/tokens/Datatoken.ts index f94beac2..ca7f6698 100644 --- a/src/tokens/Datatoken.ts +++ b/src/tokens/Datatoken.ts @@ -1168,10 +1168,12 @@ export class Datatoken { this.config ) - const estGas = await estimateGas(address, dtContract.methods.setData, value) + const valueHex = this.web3.utils.asciiToHex(value) + + const estGas = await estimateGas(address, dtContract.methods.setData, valueHex) // Call setData function of the contract - const trxReceipt = await dtContract.methods.setData(value).send({ + const trxReceipt = await dtContract.methods.setData(valueHex).send({ from: address, gas: estGas + 1, gasPrice: await getFairGasPrice(this.web3, this.config) From ec4b21fab5e03f969d8cc171b8149266d2957127 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 11 Jul 2022 23:43:57 +0200 Subject: [PATCH 6/6] adapt tests for datatoken.setData() --- test/unit/tokens/Datatoken.test.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/unit/tokens/Datatoken.test.ts b/test/unit/tokens/Datatoken.test.ts index e862e550..f25726fd 100644 --- a/test/unit/tokens/Datatoken.test.ts +++ b/test/unit/tokens/Datatoken.test.ts @@ -549,19 +549,18 @@ describe('Datatoken', () => { }) it('#setData - should set a value into 725Y standard, if Caller has ERC20Deployer permission', async () => { - const data = web3.utils.asciiToHex('SomeData') + const data = 'SomeData' assert((await nftDatatoken.isErc20Deployer(nftAddress, nftOwner)) === true) await datatoken.setData(datatokenAddress, nftOwner, data) - const key = web3.utils.keccak256(datatokenAddress) - assert((await nftDatatoken.getData(nftAddress, key)) === data) + assert((await nftDatatoken.getData(nftAddress, datatokenAddress)) === data) }) it('#setData - should FAIL to set a value into 725Y standard, if Caller has NOT ERC20Deployer permission', async () => { - const data = web3.utils.asciiToHex('NewData') - const OldData = web3.utils.asciiToHex('SomeData') + const data = 'NewData' + const OldData = 'SomeData' assert((await nftDatatoken.isErc20Deployer(nftAddress, user1)) === false) try { @@ -570,8 +569,7 @@ describe('Datatoken', () => { } catch (e) { assert(e.message === 'User is not ERC20 Deployer') } - const key = web3.utils.keccak256(datatokenAddress) - assert((await nftDatatoken.getData(nftAddress, key)) === OldData) + assert((await nftDatatoken.getData(nftAddress, datatokenAddress)) === OldData) }) it('#getDecimals - should return the number of decimals of the datatoken', async () => {