diff --git a/contracts/examples/ConfidentialNFTExample.sol b/contracts/examples/ConfidentialNFTExample.sol index 73f7f44..9fe4428 100644 --- a/contracts/examples/ConfidentialNFTExample.sol +++ b/contracts/examples/ConfidentialNFTExample.sol @@ -36,14 +36,13 @@ contract ConfidentialNFTExample is function mint( address to, - ctUint64[] calldata _itTokenURI, - bytes[] calldata _itSignature + itString calldata itTokenURI ) public onlyOwner { uint256 tokenId = _totalSupply; ConfidentialERC721._mint(to, tokenId); - ConfidentialERC721URIStorage._setTokenURI(msg.sender, tokenId, _itTokenURI, _itSignature); + ConfidentialERC721URIStorage._setTokenURI(msg.sender, tokenId, itTokenURI); _totalSupply += 1; diff --git a/contracts/examples/DataOnChain.sol b/contracts/examples/DataOnChain.sol index 2a12e38..dcb1f30 100644 --- a/contracts/examples/DataOnChain.sol +++ b/contracts/examples/DataOnChain.sol @@ -11,9 +11,9 @@ contract DataOnChain { ctUint64 private ctNetworkSomeEncryptedValue; ctUint64 private ctNetworkSomeEncryptedValueEncryptedInput; ctUint64 private ctUserArithmeticResult; - ctUint64[] private ctUserSomeEncryptedStringEncryptedInput; - ctUint64[] private ctNetworkSomeEncryptedStringEncryptedInput; - ctUint64[] private ctUserSomeEncryptedStringValue; + ctString private ctUserSomeEncryptedStringEncryptedInput; + ctString private ctNetworkSomeEncryptedStringEncryptedInput; + ctString private ctUserSomeEncryptedStringValue; @@ -23,7 +23,7 @@ contract DataOnChain { event UserEncryptedValue(address indexed _from, ctUint64 ctUserSomeEncryptedValue); - event UserEncryptedStringValue(address indexed _from, ctUint64[] ctUserSomeEncryptedStringValue); + event UserEncryptedStringValue(address indexed _from, ctString ctUserSomeEncryptedStringValue); function getNetworkSomeEncryptedValue() external view returns (ctUint64 ctSomeEncryptedValue) { @@ -46,7 +46,7 @@ contract DataOnChain { return ctUserSomeEncryptedValueEncryptedInput; } - function getUserSomeEncryptedStringEncryptedInput() external view returns (ctUint64[] memory ctSomeEncryptedValue) { + function getUserSomeEncryptedStringEncryptedInput() external view returns (ctString memory ctSomeEncryptedValue) { return ctUserSomeEncryptedStringEncryptedInput; } @@ -64,23 +64,10 @@ contract DataOnChain { ctNetworkSomeEncryptedValueEncryptedInput = MpcCore.offBoard(gtNetworkSomeEncryptedValue); // saves it as cipher text (by network aes key) } - function setSomeEncryptedStringEncryptedInput(ctUint64[] calldata _itInputString, bytes[] calldata _itSignature) external { - gtUint64[] memory _encryptedValueGt = new gtUint64[](_itInputString.length); + function setSomeEncryptedStringEncryptedInput(itString calldata _itInputString) external { + gtString memory _encryptedValueGt = MpcCore.validateCiphertext(_itInputString); - itUint64 memory it; - - for (uint256 i = 0; i < _itInputString.length; ++i) { - it.ciphertext = _itInputString[i]; - it.signature = _itSignature[i]; - - _encryptedValueGt[i] = MpcCore.validateCiphertext(it); - } - - ctUint64[] memory tmp = new ctUint64[](_itInputString.length); - for (uint256 i = 0; i < _encryptedValueGt.length; ++i) { - tmp[i] = MpcCore.offBoard(_encryptedValueGt[i]); - } - ctNetworkSomeEncryptedStringEncryptedInput = tmp; + ctNetworkSomeEncryptedStringEncryptedInput = MpcCore.offBoard(_encryptedValueGt); } function setUserSomeEncryptedValue() external { @@ -96,16 +83,9 @@ contract DataOnChain { } function setUserSomeEncryptedStringEncryptedInput() external { - gtUint64[] memory userGt = new gtUint64[](ctNetworkSomeEncryptedStringEncryptedInput.length); - - for (uint256 i = 0; i < ctNetworkSomeEncryptedStringEncryptedInput.length; ++i) { - userGt[i] = MpcCore.onBoard(ctNetworkSomeEncryptedStringEncryptedInput[i]); - } - ctUint64[] memory tmp = new ctUint64[](userGt.length); - for (uint256 i = 0; i < userGt.length; ++i) { - tmp[i] = MpcCore.offBoardToUser(userGt[i], msg.sender); - } - ctUserSomeEncryptedStringEncryptedInput = tmp; + gtString memory userGt = MpcCore.onBoard(ctNetworkSomeEncryptedStringEncryptedInput); + + ctUserSomeEncryptedStringEncryptedInput = MpcCore.offBoardToUser(userGt, msg.sender); emit UserEncryptedStringValue(msg.sender, ctUserSomeEncryptedStringEncryptedInput); } diff --git a/contracts/examples/TestMpcCore.sol b/contracts/examples/TestMpcCore.sol index 149a651..37decbc 100644 --- a/contracts/examples/TestMpcCore.sol +++ b/contracts/examples/TestMpcCore.sol @@ -4,14 +4,28 @@ pragma solidity ^0.8.19; import "../lib/MpcCore.sol"; contract TestMpcCore { + + // Encrypted string variables + ctString private userEncryptedString; ctString private networkEncryptedString; - string public plaintext; + string public plaintextString; bool public isEqual; + // Encrypted address variables + + ctAddress public userEncryptedAddress; + + ctAddress public networkEncryptedAddress; + + address public plaintextAddress; + + + // Encrypted string functions + function setUserEncryptedString(itString calldata it_) public { gtString memory gt_ = MpcCore.validateCiphertext(it_); @@ -31,7 +45,7 @@ contract TestMpcCore { function decryptNetworkEncryptedString() public { gtString memory gt_ = MpcCore.onBoard(networkEncryptedString); - plaintext = MpcCore.decrypt(gt_); + plaintextString = MpcCore.decrypt(gt_); } function setPublicString(string calldata str) public { @@ -60,4 +74,51 @@ contract TestMpcCore { userEncryptedString = MpcCore.offBoardToUser(gt_, msg.sender); } + + // Encrypted address function + + function setUserEncryptedAddress(itAddress calldata it_) public { + gtAddress memory gt_ = MpcCore.validateCiphertext(it_); + + userEncryptedAddress = MpcCore.offBoardToUser(gt_, msg.sender); + } + + function setNetworkEncryptedAddress(itAddress calldata it_) public { + gtAddress memory gt_ = MpcCore.validateCiphertext(it_); + + networkEncryptedAddress = MpcCore.offBoard(gt_); + } + + function decryptNetworkEncryptedAddress() public { + gtAddress memory gt_ = MpcCore.onBoard(networkEncryptedAddress); + + plaintextAddress = MpcCore.decrypt(gt_); + } + + function setPublicAddress(address addr) public { + gtAddress memory gt_ = MpcCore.setPublicAddress(addr); + + userEncryptedAddress = MpcCore.offBoardToUser(gt_, msg.sender); + } + + function setIsEqual(itAddress calldata a_, itAddress calldata b_, bool useEq) public { + gtAddress memory a = MpcCore.validateCiphertext(a_); + gtAddress memory b = MpcCore.validateCiphertext(b_); + + gtBool isEqual_; + + if (useEq) { + isEqual_ = MpcCore.eq(a, b); + } else { + isEqual_ = MpcCore.not(MpcCore.ne(a, b)); + } + + isEqual = MpcCore.decrypt(isEqual_); + } + + function setRandomAddress() public { + gtAddress memory gt_ = MpcCore.randAddress(); + + userEncryptedAddress = MpcCore.offBoardToUser(gt_, msg.sender); + } } diff --git a/contracts/lib/MpcCore.sol b/contracts/lib/MpcCore.sol index a9a2c76..72b4f02 100644 --- a/contracts/lib/MpcCore.sol +++ b/contracts/lib/MpcCore.sol @@ -14,6 +14,12 @@ struct gtString { gtUint64[] value; } +struct gtAddress { + gtUint64 gt1; // bytes 1 - 8 + gtUint64 gt2; // bytes 9 - 16 + gtUint32 gt3; // bytes 17 - 20 +} + type ctBool is uint256; type ctUint8 is uint256; type ctUint16 is uint256; @@ -26,6 +32,12 @@ struct ctString { ctUint64[] value; } +struct ctAddress { + ctUint64 ct1; // bytes 1 - 8 + ctUint64 ct2; // bytes 9 - 16 + ctUint32 ct3; // bytes 17 - 20 +} + struct itBool { ctBool ciphertext; bytes signature; @@ -50,6 +62,12 @@ struct itString { ctString ciphertext; bytes[] signature; } +struct itAddress { + ctAddress ciphertext; + bytes signature1; + bytes signature2; + bytes signature3; +} struct utBool { ctBool ciphertext; @@ -75,6 +93,10 @@ struct utString { ctString ciphertext; ctString userCiphertext; } +struct utAddress { + ctAddress ciphertext; + ctAddress userCiphertext; +} import "./MpcInterface.sol"; @@ -991,6 +1013,112 @@ library MpcCore { + // ========== Address operations =========== + + function validateCiphertext(itAddress memory input) internal returns (gtAddress memory) { + gtAddress memory gt_; + + itUint64 memory it1_; + + it1_.ciphertext = input.ciphertext.ct1; + it1_.signature = input.signature1; + gt_.gt1 = validateCiphertext(it1_); + + it1_.ciphertext = input.ciphertext.ct2; + it1_.signature = input.signature2; + gt_.gt2 = validateCiphertext(it1_); + + itUint32 memory it2_ = itUint32(input.ciphertext.ct3, input.signature3); + gt_.gt3 = validateCiphertext(it2_); + + return gt_; + } + + function onBoard(ctAddress memory ct) internal returns (gtAddress memory) { + gtAddress memory gt_; + + gt_.gt1 = onBoard(ct.ct1); + gt_.gt2 = onBoard(ct.ct2); + gt_.gt3 = onBoard(ct.ct3); + + return gt_; + } + + function offBoard(gtAddress memory pt) internal returns (ctAddress memory) { + ctAddress memory ct_; + + ct_.ct1 = offBoard(pt.gt1); + ct_.ct2 = offBoard(pt.gt2); + ct_.ct3 = offBoard(pt.gt3); + + return ct_; + } + + function offBoardToUser(gtAddress memory pt, address addr) internal returns (ctAddress memory) { + ctAddress memory ct_; + + ct_.ct1 = offBoardToUser(pt.gt1, addr); + ct_.ct2 = offBoardToUser(pt.gt2, addr); + ct_.ct3 = offBoardToUser(pt.gt3, addr); + + return ct_; + } + + function offBoardCombined(gtAddress memory pt, address addr) internal returns (utAddress memory ut) { + ut.ciphertext = offBoard(pt); + ut.userCiphertext = offBoardToUser(pt, addr); + } + + function setPublicAddress(address pt) internal returns (gtAddress memory) { + gtAddress memory result_; + + result_.gt1 = setPublic64(uint64(bytes8(bytes20(pt)))); + result_.gt2 = setPublic64(uint64(bytes8(bytes20(pt) << 64))); + result_.gt3 = setPublic32(uint32(bytes4(bytes20(pt) << 128))); + + return result_; + } + + function randAddress() internal returns (gtAddress memory) { + gtAddress memory result_; + + result_.gt1 = rand64(); + result_.gt2 = rand64(); + result_.gt3 = rand32(); + + return result_; + } + + function decrypt(gtAddress memory ct) internal returns (address){ + bytes20 result_; + + result_ |= bytes20(bytes8(decrypt(ct.gt1))); + result_ |= bytes20(bytes8(decrypt(ct.gt2))) >> 64; + result_ |= bytes20(bytes4(decrypt(ct.gt3))) >> 128; + + return address(result_); + } + + function eq(gtAddress memory a, gtAddress memory b) internal returns (gtBool) { + gtBool result_ = eq(a.gt1, b.gt1); + + result_ = and(result_, eq(a.gt2, b.gt2)); + result_ = and(result_, eq(a.gt3, b.gt3)); + + return result_; + } + + function ne(gtAddress memory a, gtAddress memory b) internal returns (gtBool) { + gtBool result_ = ne(a.gt1, b.gt1); + + result_ = or(result_, ne(a.gt2, b.gt2)); + result_ = or(result_, ne(a.gt3, b.gt3)); + + return result_; + } + + + // =========== Operations with LHS_PUBLIC parameter =========== // =========== 8 bit operations ============== diff --git a/contracts/token/ERC721/ConfidentialERC721URIStorage.sol b/contracts/token/ERC721/ConfidentialERC721URIStorage.sol index 99993ad..697dfed 100644 --- a/contracts/token/ERC721/ConfidentialERC721URIStorage.sol +++ b/contracts/token/ERC721/ConfidentialERC721URIStorage.sol @@ -9,7 +9,7 @@ import "../../lib/MpcCore.sol"; * @dev ConfidentialERC721 token with storage based token URI management. */ abstract contract ConfidentialERC721URIStorage is IERC165, ConfidentialERC721 { - mapping(uint256 tokenId => utUint64[]) private _tokenURIs; + mapping(uint256 tokenId => utString) private _tokenURIs; event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); @@ -25,16 +25,16 @@ abstract contract ConfidentialERC721URIStorage is IERC165, ConfidentialERC721 { return interfaceId == type(ConfidentialERC721).interfaceId; } - function tokenURI(uint256 tokenId) public view virtual returns (ctUint64[] memory) { - utUint64[] memory _tokenURI = _tokenURIs[tokenId]; + function tokenURI(uint256 tokenId) public view virtual returns (ctString memory) { + // utUint64[] memory _tokenURI = _tokenURIs[tokenId]; - ctUint64[] memory _userTokenURI = new ctUint64[](_tokenURIs[tokenId].length); + // ctUint64[] memory _userTokenURI = new ctUint64[](_tokenURIs[tokenId].length); - for (uint256 i = 0; i < _tokenURI.length; ++i) { - _userTokenURI[i] = _tokenURI[i].userCiphertext; - } + // for (uint256 i = 0; i < _tokenURI.length; ++i) { + // _userTokenURI[i] = _tokenURI[i].userCiphertext; + // } - return _userTokenURI; + return _tokenURIs[tokenId].userCiphertext; } /** @@ -44,18 +44,17 @@ abstract contract ConfidentialERC721URIStorage is IERC165, ConfidentialERC721 { function _setTokenURI( address to, uint256 tokenId, - ctUint64[] calldata _itTokenURI, - bytes[] calldata _itSignature + itString calldata itTokenURI ) internal virtual { - gtUint64[] memory _tokenURI = new gtUint64[](_itTokenURI.length); + gtString memory _tokenURI = gtString(new gtUint64[](itTokenURI.ciphertext.value.length)); itUint64 memory it; - for (uint256 i = 0; i < _itTokenURI.length; ++i) { - it.ciphertext = _itTokenURI[i]; - it.signature = _itSignature[i]; + for (uint256 i = 0; i < itTokenURI.ciphertext.value.length; ++i) { + it.ciphertext = itTokenURI.ciphertext.value[i]; + it.signature = itTokenURI.signature[i]; - _tokenURI[i] = MpcCore.validateCiphertext(it); + _tokenURI.value[i] = MpcCore.validateCiphertext(it); } _setTokenURI(to, tokenId, _tokenURI, true); @@ -68,37 +67,20 @@ abstract contract ConfidentialERC721URIStorage is IERC165, ConfidentialERC721 { function _setTokenURI( address to, uint256 tokenId, - gtUint64[] memory _tokenURI, + gtString memory _tokenURI, bool updateCiphertext ) private { if (ownerOf(tokenId) == address(0)) { revert ERC721URIStorageNonMintedToken(tokenId); } - // we must first make sure that tokenURI has the correct length - utUint64[] storage tokenURI = _tokenURIs[tokenId]; - - utUint64 memory offBoardCombined; + utString memory offBoardCombined = MpcCore.offBoardCombined(_tokenURI, to); if (updateCiphertext) { - for (uint256 i = 0; i < _tokenURI.length; ++i) { - offBoardCombined = MpcCore.offBoardCombined(_tokenURI[i], to); - - tokenURI.push(offBoardCombined); - } - - _tokenURIs[tokenId] = tokenURI; + _tokenURIs[tokenId] = offBoardCombined; } else { - for (uint256 i = 0; i < _tokenURI.length; ++i) { - offBoardCombined = MpcCore.offBoardCombined(_tokenURI[i], to); - - tokenURI[i].userCiphertext = offBoardCombined.userCiphertext; - } - - _tokenURIs[tokenId] = tokenURI; + _tokenURIs[tokenId].userCiphertext = offBoardCombined.userCiphertext; } - - } function _update( @@ -106,12 +88,12 @@ abstract contract ConfidentialERC721URIStorage is IERC165, ConfidentialERC721 { uint256 tokenId, address auth ) internal virtual override returns (address) { - utUint64[] memory _tokenURI = _tokenURIs[tokenId]; + ctString memory _tokenURI = _tokenURIs[tokenId].ciphertext; - gtUint64[] memory _networkTokenURI = new gtUint64[](_tokenURI.length); + gtString memory _networkTokenURI = gtString(new gtUint64[](_tokenURI.value.length)); - for (uint256 i = 0; i < _networkTokenURI.length; ++i) { - _networkTokenURI[i] = MpcCore.onBoard(_tokenURI[i].ciphertext); + for (uint256 i = 0; i < _networkTokenURI.value.length; ++i) { + _networkTokenURI.value[i] = MpcCore.onBoard(_tokenURI.value[i]); } // reencrypt with the new user key diff --git a/package.json b/package.json index 0f96fa0..153c08c 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "test": "yarn hardhat test" }, "devDependencies": { - "@coti-io/coti-sdk-typescript": "0.6.3", + "@coti-io/coti-sdk-typescript": "file:../coti-sdk-typescript", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", "@nomicfoundation/hardhat-ignition": "^0.15.0", diff --git a/test-hardhat/confidential-auction.test.ts b/test-hardhat/confidential-auction.test.ts index 808b282..c4cdf83 100644 --- a/test-hardhat/confidential-auction.test.ts +++ b/test-hardhat/confidential-auction.test.ts @@ -86,8 +86,8 @@ describe("Confidential Auction", function () { const func = contract.connect(owner.wallet).bid const selector = func.fragment.selector - const { ctInt, signature } = await buildInputText(BigInt(bidAmount), owner, contractAddress, selector) - await (await func(ctInt, signature, { gasLimit })).wait() + const { ciphertext, signature } = await buildInputText(BigInt(bidAmount), owner, contractAddress, selector) + await (await func(ciphertext, signature, { gasLimit })).wait() await expectBalance(token, initialBalance - bidAmount, owner) @@ -103,8 +103,8 @@ describe("Confidential Auction", function () { const func = contract.connect(owner.wallet).bid const selector = func.fragment.selector - const { ctInt, signature } = await buildInputText(BigInt(bidAmount * 2), owner, contractAddress, selector) - await (await func(ctInt, signature, { gasLimit })).wait() + const { ciphertext, signature } = await buildInputText(BigInt(bidAmount * 2), owner, contractAddress, selector) + await (await func(ciphertext, signature, { gasLimit })).wait() await expectBalance(token, initialBalance - bidAmount, owner) diff --git a/test-hardhat/confidential-erc20.test.ts b/test-hardhat/confidential-erc20.test.ts index 5b3a9e7..ce55138 100644 --- a/test-hardhat/confidential-erc20.test.ts +++ b/test-hardhat/confidential-erc20.test.ts @@ -109,9 +109,9 @@ describe("Confidential ERC20", function () { const func = contract.connect(owner.wallet)["transfer(address,uint256,bytes,bool)"] const selector = func.fragment.selector - const { ctInt, signature } = await buildInputText(BigInt(transferAmount), owner, contractAddress, selector) + const { ciphertext, signature } = await buildInputText(BigInt(transferAmount), owner, contractAddress, selector) - await (await func(otherAccount.wallet.address, ctInt, signature, false, { gasLimit })).wait() + await (await func(otherAccount.wallet.address, ciphertext, signature, false, { gasLimit })).wait() await expectBalance(contract, initialBalance - transferAmount, owner) }) @@ -148,9 +148,9 @@ describe("Confidential ERC20", function () { const func = contract.connect(owner.wallet)["transferFrom(address,address,uint256,bytes,bool)"] const selector = func.fragment.selector - let { ctInt, signature } = await buildInputText(BigInt(transferAmount), owner, contractAddress, selector) + let { ciphertext, signature } = await buildInputText(BigInt(transferAmount), owner, contractAddress, selector) await ( - await func(owner.wallet.address, otherAccount.wallet.address, ctInt, signature, false, { gasLimit }) + await func(owner.wallet.address, otherAccount.wallet.address, ciphertext, signature, false, { gasLimit }) ).wait() await expectBalance(contract, initialBalance - transferAmount, owner) @@ -164,8 +164,8 @@ describe("Confidential ERC20", function () { const func = contract.connect(owner.wallet)["approve(address,uint256,bytes)"] const selector = func.fragment.selector - const { ctInt, signature } = await buildInputText(BigInt(transferAmount), owner, contractAddress, selector) - await (await func(otherAccount.wallet.address, ctInt, signature, { gasLimit })).wait() + const { ciphertext, signature } = await buildInputText(BigInt(transferAmount), owner, contractAddress, selector) + await (await func(otherAccount.wallet.address, ciphertext, signature, { gasLimit })).wait() await expectAllowance(contract, transferAmount, owner, otherAccount.wallet.address) }) diff --git a/test-hardhat/confidential-identity.test.ts b/test-hardhat/confidential-identity.test.ts index 948c0ef..575eaf5 100644 --- a/test-hardhat/confidential-identity.test.ts +++ b/test-hardhat/confidential-identity.test.ts @@ -34,8 +34,8 @@ describe("Confidential Identity", function () { const func = contract.connect(owner.wallet).setIdentifier const selector = func.fragment.selector - const { ctInt, signature } = await buildInputText(BigInt(idAge), owner, contractAddress, selector) - await (await func(owner.wallet.address, "age", ctInt, signature, { gasLimit })).wait() + const { ciphertext, signature } = await buildInputText(BigInt(idAge), owner, contractAddress, selector) + await (await func(owner.wallet.address, "age", ciphertext, signature, { gasLimit })).wait() await (await contract.grantAccess(deployment.owner.wallet.address, ["age"], { gasLimit })).wait() diff --git a/test-hardhat/confidential-nft.test.ts b/test-hardhat/confidential-nft.test.ts index 00950c5..73991e6 100644 --- a/test-hardhat/confidential-nft.test.ts +++ b/test-hardhat/confidential-nft.test.ts @@ -51,15 +51,14 @@ describe("Confidential NFT", function () { before(async function () { const { contract, contractAddress, owner, otherAccount } = deployment - const encryptedTokenURI = await buildStringInputText(tokenURI, owner, contractAddress, contract.mint.fragment.selector) + const itTokenURI = await buildStringInputText(tokenURI, owner, contractAddress, contract.mint.fragment.selector) tx = await ( await contract .connect(owner.wallet) .mint( otherAccount.wallet.address, - encryptedTokenURI.map((val) => val.ciphertext), - encryptedTokenURI.map((val) => val.signature), + itTokenURI, { gasLimit }) ).wait() }) @@ -87,14 +86,13 @@ describe("Confidential NFT", function () { it("Should fail to mint if not owner", async function () { const { contract, contractAddress, otherAccount } = deployment - const encryptedTokenURI = await buildStringInputText(tokenURI, otherAccount, contractAddress, contract.mint.fragment.selector) + const itTokenURI = await buildStringInputText(tokenURI, otherAccount, contractAddress, contract.mint.fragment.selector) const tx = await contract .connect(otherAccount.wallet) .mint( otherAccount.wallet.address, - encryptedTokenURI.map((val) => val.ciphertext), - encryptedTokenURI.map((val) => val.signature), + itTokenURI, { gasLimit } ) @@ -104,15 +102,19 @@ describe("Confidential NFT", function () { it("Should fail to mint if the encrypted token URI is faulty", async function () { const { contract, contractAddress, otherAccount } = deployment - const ownerEncryptedTokenURI = await buildStringInputText(tokenURI, otherAccount, contractAddress, contract.mint.fragment.selector) - const otherAccountEncryptedTokenURI = await buildStringInputText(tokenURI, otherAccount, contractAddress, contract.mint.fragment.selector) + const ownerItTokenURI = await buildStringInputText(tokenURI, otherAccount, contractAddress, contract.mint.fragment.selector) + const otherAccountItTokenURI = await buildStringInputText(tokenURI, otherAccount, contractAddress, contract.mint.fragment.selector) + + const itTokenURI = { + ciphertext: ownerItTokenURI.ciphertext, + signature: otherAccountItTokenURI.signature + } const tx = await contract .connect(otherAccount.wallet) .mint( otherAccount.wallet.address, - ownerEncryptedTokenURI.map((val) => val.ciphertext), - otherAccountEncryptedTokenURI.map((val) => val.signature), + itTokenURI, { gasLimit } ) @@ -184,7 +186,7 @@ describe("Confidential NFT", function () { it("Should fail transfer token to other account for when no allowance", async function () { const { contract, contractAddress, owner, otherAccount } = deployment - const encryptedTokenURI = await buildStringInputText(tokenURI, owner, contractAddress, contract.mint.fragment.selector) + const itTokenURI = await buildStringInputText(tokenURI, owner, contractAddress, contract.mint.fragment.selector) const tokenId = await deployment.contract.totalSupply() @@ -193,8 +195,7 @@ describe("Confidential NFT", function () { .connect(owner.wallet) .mint( owner.wallet.address, - encryptedTokenURI.map((val) => val.ciphertext), - encryptedTokenURI.map((val) => val.signature), + itTokenURI, { gasLimit } ) ).wait() @@ -213,7 +214,7 @@ describe("Confidential NFT", function () { it("Should fail to transfer from non-owner", async function () { const { contract, contractAddress, owner, otherAccount } = deployment - const encryptedTokenURI = await buildStringInputText(tokenURI, owner, contractAddress, contract.mint.fragment.selector) + const itTokenURI = await buildStringInputText(tokenURI, owner, contractAddress, contract.mint.fragment.selector) const tokenId = await deployment.contract.totalSupply() @@ -222,8 +223,7 @@ describe("Confidential NFT", function () { .connect(owner.wallet) .mint( owner.wallet.address, - encryptedTokenURI.map((val) => val.ciphertext), - encryptedTokenURI.map((val) => val.signature), + itTokenURI, { gasLimit } ) ).wait() diff --git a/test-hardhat/mpc-core.test.ts b/test-hardhat/mpc-core.test.ts index 3698a15..8e3a36c 100644 --- a/test-hardhat/mpc-core.test.ts +++ b/test-hardhat/mpc-core.test.ts @@ -1,9 +1,7 @@ import hre from "hardhat" import { expect } from "chai" import { setupAccounts } from "./util/onboard" -import { BaseWallet, BigNumberish, ContractTransactionReceipt } from "ethers" -import { ConfidentialAccount, decryptUint, buildInputText } from "@coti-io/coti-sdk-typescript" -import { CtStringStruct, ItStringStruct } from "../typechain-types/contracts/examples/TestMpcCore" +import { buildAddressInputText, buildStringInputText, decryptAddress, decryptString } from "@coti-io/coti-sdk-typescript" const gasLimit = 12000000 @@ -17,53 +15,6 @@ async function deploy() { return { contract, contractAddress: await contract.getAddress(), owner, otherAccount } } -function prepareStringIT( - plaintext: string, - sender: { wallet: BaseWallet, userKey: string }, - contractAddress: string, - functionSelector: string -) { - const strBuffer = Buffer.from(plaintext) - - const itString: ItStringStruct = { - ciphertext: { value: new Array }, - signature: new Array - } - - for (let i = 0; i < strBuffer.length / 8; i++) { - const startIdx = i * 8 - const endIdx = Math.min((i * 8) + 8, strBuffer.length) - - const byteArr = Buffer.concat([strBuffer.slice(startIdx, endIdx), Buffer.alloc(8 - (endIdx - startIdx))]) - - const encryptedCell = buildInputText( - BigInt("0x" + byteArr.toString('hex')), - sender, - contractAddress, - functionSelector - ) - - itString.ciphertext.value.push(encryptedCell.ctInt) - itString.signature.push(encryptedCell.signature) - } - - return itString -} - -function decryptString(ciphertext: CtStringStruct, owner: ConfidentialAccount) { - let strBuffer = Buffer.alloc(0) - - for (let i = 0; i < ciphertext.value.length; i++) { - const decrypted = decryptUint(BigInt(ciphertext.value[i]), owner.userKey) - - strBuffer = Buffer.concat([strBuffer, Buffer.from(decrypted.toString(16), 'hex')]) - } - - const decryptedStr = strBuffer.toString() - - return formatString(decryptedStr) -} - function formatString(str: string) { return str.replace(/\0/g, '') } @@ -75,13 +26,14 @@ describe("MPC Core", function () { deployment = await deploy() }) - describe("Set user-encrypted string using an encrypted value", function () { - const str = "Hello, World!" + describe("Encrypted Strings", function () { + describe("Set user-encrypted string using an encrypted value", function () { + const str = "Hello, World!" it("Should store the string encrypted using the users key", async function () { const { contract, contractAddress, owner } = deployment - const itString = prepareStringIT( + const itString = buildStringInputText( str, { wallet: owner.wallet, userKey: owner.userKey }, contractAddress, @@ -91,38 +43,38 @@ describe("MPC Core", function () { const tx = await contract .connect(owner.wallet) .setUserEncryptedString(itString, { gasLimit }) - - await tx.wait() - }) + + await tx.wait() + }) - it("Should retrieve the string encrypted with the users key", async function () { - const { contract, owner } = deployment + it("Should retrieve the string encrypted with the users key", async function () { + const { contract, owner } = deployment - const userEncryptedString = await contract.getUserEncryptedString() + const userEncryptedString = await contract.getUserEncryptedString() - const decryptedStr = decryptString(userEncryptedString, owner) + const decryptedStr = decryptString(userEncryptedString, owner.userKey) - expect(decryptedStr).to.equal(str) - }) + expect(decryptedStr).to.equal(str) + }) - it("Should fail to decrypt the string encrypted with the users key", async function () { - const { contract, otherAccount } = deployment + it("Should fail to decrypt the string encrypted with the users key", async function () { + const { contract, otherAccount } = deployment - const userEncryptedString = await contract.getUserEncryptedString() + const userEncryptedString = await contract.getUserEncryptedString() - const decryptedStr = decryptString(userEncryptedString, otherAccount) + const decryptedStr = decryptString(userEncryptedString, otherAccount.userKey) - expect(decryptedStr).to.not.equal(str) + expect(decryptedStr).to.not.equal(str) + }) }) - }) - describe("Set network-encrypted string using an encrypted value", function () { - const str = "Hi, Mom!" + describe("Set network-encrypted string using an encrypted value", function () { + const str = "Hi, Mom!" it("Should store the string encrypted using the network key", async function () { const { contract, contractAddress, owner } = deployment - const itString = prepareStringIT( + const itString = buildStringInputText( str, { wallet: owner.wallet, userKey: owner.userKey }, contractAddress, @@ -132,152 +84,394 @@ describe("MPC Core", function () { const tx = await contract .connect(owner.wallet) .setNetworkEncryptedString(itString, { gasLimit }) - - await tx.wait() - }) + + await tx.wait() + }) - it("Should decrypt the network-encrypted string and store it in clear text", async function () { - const { contract, owner } = deployment + it("Should decrypt the network-encrypted string and store it in clear text", async function () { + const { contract, owner } = deployment - const tx = await contract - .connect(owner.wallet) - .decryptNetworkEncryptedString() + const tx = await contract + .connect(owner.wallet) + .decryptNetworkEncryptedString() - await tx.wait() + await tx.wait() - const decryptedStr = await contract.plaintext() + const decryptedStr = await contract.plaintextString() - expect(formatString(decryptedStr)).to.equal(str) + expect(formatString(decryptedStr)).to.equal(str) + }) }) - }) - describe("Set user-encrypted string using a non-encrypted value", function () { - const str = "Hello darkness, my old friend." + describe("Set user-encrypted string using a non-encrypted value", function () { + const str = "Hello darkness, my old friend." it("Should store the string encrypted using the users key", async function () { const { contract, owner } = deployment - const tx = await contract - .connect(owner.wallet) - .setPublicString(str, { gasLimit }) + const tx = await contract + .connect(owner.wallet) + .setPublicString(str, { gasLimit }) - await tx.wait() - }) + await tx.wait() + }) - it("Should retrieve the string encrypted with the users key", async function () { - const { contract, owner } = deployment + it("Should retrieve the string encrypted with the users key", async function () { + const { contract, owner } = deployment - const userEncryptedString = await contract.getUserEncryptedString() + const userEncryptedString = await contract.getUserEncryptedString() - const decryptedStr = decryptString(userEncryptedString, owner) + const decryptedStr = decryptString(userEncryptedString, owner.userKey) - expect(decryptedStr).to.equal(str) + expect(decryptedStr).to.equal(str) + }) }) - }) - describe("Set isEqual using two encrypted values", function () { - const a = "ABC" - const b = "DEF" + describe("Set isEqual using two encrypted values", function () { + const a = "ABC" + const b = "DEF" + + describe("Using eq", function () { + it("Should set isEqual to true", async function () { + const { contract, contractAddress, owner } = deployment + + const itString = buildStringInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"](itString, itString, true, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(true) + }) + + it("Should set isEqual to false", async function () { + const { contract, contractAddress, owner } = deployment + + const itStringA = buildStringInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"].fragment.selector + ) + + const itStringB = buildStringInputText( + b, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"](itStringA, itStringB, true, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(false) + }) + }) + + describe("Using ne", function () { + it("Should set isEqual to true", async function () { + const { contract, contractAddress, owner } = deployment + + const itStringA = buildStringInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"].fragment.selector + ) + + const itStringB = buildStringInputText( + b, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"](itStringA, itStringB, false, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(false) + }) - describe("Using eq", function () { - it("Should set isEqual to true", async function () { - const { contract, contractAddress, owner } = deployment + it("Should set isEqual to false", async function () { + const { contract, contractAddress, owner } = deployment + + const itString = buildStringInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256[]),bytes[]),((uint256[]),bytes[]),bool)"](itString, itString, false, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(true) + }) + }) + }) + + describe("Encrypted Addresses", function () { + describe("Set user-encrypted address using encrypted value", function () { + const addr = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' // vitalik.eth + + it("Should store the address encrypted using the users key", async function () { + const { contract, contractAddress, owner } = deployment + + const itAddress = buildAddressInputText( + addr, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract.setUserEncryptedAddress.fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + .setUserEncryptedAddress(itAddress, { gasLimit }) + + await tx.wait() + }) - const itString = prepareStringIT( - a, - { wallet: owner.wallet, userKey: owner.userKey }, - contractAddress, - contract.setIsEqual.fragment.selector - ) + it("Should retrieve the address encrypted with the users key", async function () { + const { contract, owner } = deployment - const tx = await contract - .connect(owner.wallet) - .setIsEqual(itString, itString, true, { gasLimit }) - - await tx.wait() + const userEncryptedAddress = await contract.userEncryptedAddress() - const isEqual = await contract.isEqual() + const decryptedAddress = decryptAddress(userEncryptedAddress, owner.userKey) - expect(isEqual).to.equal(true) - }) + expect(decryptedAddress).to.equal(addr) + }) - it("Should set isEqual to false", async function () { - const { contract, contractAddress, owner } = deployment + it("Should fail to decrypt the string encrypted with the users key", async function () { + const { contract, otherAccount } = deployment - const itStringA = prepareStringIT( - a, - { wallet: owner.wallet, userKey: owner.userKey }, - contractAddress, - contract.setIsEqual.fragment.selector - ) + const userEncryptedAddr = await contract.userEncryptedAddress() - const itStringB = prepareStringIT( - b, - { wallet: owner.wallet, userKey: owner.userKey }, - contractAddress, - contract.setIsEqual.fragment.selector - ) + let success = false + + // decryption will fail because the output will not be a valid address + try { + decryptAddress(userEncryptedAddr, otherAccount.userKey) + success = true + } catch (e) { + success = false + } - const tx = await contract - .connect(owner.wallet) - .setIsEqual(itStringA, itStringB, true, { gasLimit }) + expect(success).to.equal(false) + }) + }) + + describe("Set network-encrypted address using an encrypted value", function () { + const addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" // WETH + + it("Should store the address encrypted using the network key", async function () { + const { contract, contractAddress, owner } = deployment - await tx.wait() + const itAddress = buildAddressInputText( + addr, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract.setNetworkEncryptedAddress.fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + .setNetworkEncryptedAddress(itAddress, { gasLimit }) + + await tx.wait() + }) + + it("Should decrypt the network-encrypted address and store it in clear text", async function () { + const { contract, owner } = deployment + + const tx = await contract + .connect(owner.wallet) + .decryptNetworkEncryptedAddress() - const isEqual = await contract.isEqual() + await tx.wait() - expect(isEqual).to.equal(false) + const decryptedAddress = await contract.plaintextAddress() + + expect(decryptedAddress).to.equal(addr) + }) }) - }) - describe("Using ne", function () { - it("Should set isEqual to true", async function () { - const { contract, contractAddress, owner } = deployment + describe("Set user-encrypted address using a non-encrypted value", function () { + const addr = "0xdAC17F958D2ee523a2206206994597C13D831ec7" // USDT - const itStringA = prepareStringIT( - a, - { wallet: owner.wallet, userKey: owner.userKey }, - contractAddress, - contract.setIsEqual.fragment.selector - ) + it("Should store the address encrypted using the network key", async function () { + const { contract, owner } = deployment - const itStringB = prepareStringIT( - b, - { wallet: owner.wallet, userKey: owner.userKey }, - contractAddress, - contract.setIsEqual.fragment.selector - ) + const tx = await contract + .connect(owner.wallet) + .setPublicAddress(addr, { gasLimit }) - const tx = await contract - .connect(owner.wallet) - .setIsEqual(itStringA, itStringB, false, { gasLimit }) - - await tx.wait() + await tx.wait() + }) + + it("Should retrieve the address encrypted with the users key", async function () { + const { contract, owner } = deployment - const isEqual = await contract.isEqual() + const userEncryptedAddress = await contract.userEncryptedAddress() - expect(isEqual).to.equal(false) + const decryptedAddress = decryptAddress(userEncryptedAddress, owner.userKey) + + expect(decryptedAddress).to.equal(addr) + }) }) - it("Should set isEqual to false", async function () { - const { contract, contractAddress, owner } = deployment + describe("Set isEqual using two encrypted values", function () { + const a = "0x0000000000000000000000000000000000000001" + const b = "0x0000000000000000000000000000000000000002" - const itString = prepareStringIT( - a, - { wallet: owner.wallet, userKey: owner.userKey }, - contractAddress, - contract.setIsEqual.fragment.selector - ) + describe("Using eq", function () { + it("Should set isEqual to false", async function () { + const { contract, contractAddress, owner } = deployment + + const itAddressA = buildAddressInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"].fragment.selector + ) + + const itAddressB = buildAddressInputText( + b, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"](itAddressA, itAddressB, true, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(false) + }) + + it("Should set isEqual to true", async function () { + const { contract, contractAddress, owner } = deployment + + const itAddress = buildAddressInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"](itAddress, itAddress, true, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(true) + }) + }) - const tx = await contract - .connect(owner.wallet) - .setIsEqual(itString, itString, false, { gasLimit }) + describe("Using ne", function () { + it("Should set isEqual to false", async function () { + const { contract, contractAddress, owner } = deployment - await tx.wait() + const itAddressA = buildAddressInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"].fragment.selector + ) + + const itAddressB = buildAddressInputText( + b, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"](itAddressA, itAddressB, false, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(false) + }) + + it("Should set isEqual to true", async function () { + const { contract, contractAddress, owner } = deployment + + const itAddress = buildAddressInputText( + a, + { wallet: owner.wallet, userKey: owner.userKey }, + contractAddress, + contract["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"].fragment.selector + ) + + const tx = await contract + .connect(owner.wallet) + ["setIsEqual(((uint256,uint256,uint256),bytes,bytes,bytes),((uint256,uint256,uint256),bytes,bytes,bytes),bool)"](itAddress, itAddress, false, { gasLimit }) + + await tx.wait() + + const isEqual = await contract.isEqual() + + expect(isEqual).to.equal(true) + }) + }) + }) + + describe("Set user-encrypted address using a random value", function () { + const addr = "0xdAC17F958D2ee523a2206206994597C13D831ec7" // USDT + + it("Should store the address encrypted using the network key", async function () { + const { contract, owner } = deployment + + const tx = await contract + .connect(owner.wallet) + .setRandomAddress({ gasLimit }) + + await tx.wait() + }) + + it("Should retrieve the address encrypted with the users key", async function () { + const { contract, owner } = deployment + + const userEncryptedAddress = await contract.userEncryptedAddress() - const isEqual = await contract.isEqual() + const decryptedAddress = decryptAddress(userEncryptedAddress, owner.userKey) - expect(isEqual).to.equal(true) + expect(decryptedAddress).to.not.equal(addr) + }) }) }) }) @@ -300,7 +494,7 @@ describe("MPC Core", function () { const userEncryptedString = await contract.getUserEncryptedString() - const decryptedStr = decryptString(userEncryptedString, owner) + const decryptedStr = decryptString(userEncryptedString, owner.userKey) expect(decryptedStr).to.not.equal(str) }) diff --git a/test-hardhat/util/onboard.ts b/test-hardhat/util/onboard.ts index 9ce5d00..f2bb374 100644 --- a/test-hardhat/util/onboard.ts +++ b/test-hardhat/util/onboard.ts @@ -7,8 +7,8 @@ let pks = process.env.SIGNING_KEYS ? process.env.SIGNING_KEYS.split(",") : [] export async function setupAccounts() { if (pks.length == 0) { - const key1 = hre.ethers.Wallet.createRandom(hre.ethers.provider) - const key2 = hre.ethers.Wallet.createRandom(hre.ethers.provider) + const key1 = Wallet.createRandom(hre.ethers.provider) + const key2 = Wallet.createRandom(hre.ethers.provider) pks = [key1.privateKey, key2.privateKey] setEnvValue("PUBLIC_KEYS", `${key1.address},${key2.address}`) diff --git a/yarn.lock b/yarn.lock index 9b7d830..0c95040 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,10 +7,8 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== -"@coti-io/coti-sdk-typescript@0.6.3": - version "0.6.3" - resolved "https://registry.yarnpkg.com/@coti-io/coti-sdk-typescript/-/coti-sdk-typescript-0.6.3.tgz#9649810fd443991de366c386827c10932a2804c9" - integrity sha512-F3Omb7w/Qhn5q4rPLw4TuUiKnG2fXbzxeuYMBMWVcXj6T0c3YRwRU5LHaLAEZxS6qvCJNgjOpNqPwxVveEjZpg== +"@coti-io/coti-sdk-typescript@file:../coti-sdk-typescript": + version "0.5.5" dependencies: node-forge "^1.3.1" @@ -908,11 +906,11 @@ integrity sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw== "@types/node@*", "@types/node@>=18.0.0": - version "22.2.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.2.0.tgz#7cf046a99f0ba4d628ad3088cb21f790df9b0c5b" - integrity sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ== + version "22.4.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.4.0.tgz#c295fe1d6f5f58916cc61dbef8cf65b5b9b71de9" + integrity sha512-49AbMDwYUz7EXxKU/r7mXOsxwFr4BYbvB7tWYxVuLdb2ibd30ijjXINSMAHiEEZk5PCRBmW1gUeisn2VMKt3cQ== dependencies: - undici-types "~6.13.0" + undici-types "~6.19.2" "@types/node@18.15.13": version "18.15.13" @@ -1144,9 +1142,9 @@ at-least-node@^1.0.0: integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== axios@^1.5.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.3.tgz#a1125f2faf702bc8e8f2104ec3a76fab40257d85" - integrity sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw== + version "1.7.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" + integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -1644,9 +1642,9 @@ elliptic@6.5.4: minimalistic-crypto-utils "^1.0.1" elliptic@^6.5.2, elliptic@^6.5.4: - version "6.5.6" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.6.tgz#ee5f7c3a00b98a2144ac84d67d01f04d438fa53e" - integrity sha512-mpzdtpeCLuS3BmE3pO3Cpp5bbjlOPY2Q0PgoF+Od1XZrHLYI28Xe3ossCmYCQt11FQKEYd9+PF8jymTvtWJSHQ== + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -2392,9 +2390,9 @@ iconv-lite@0.4.24: safer-buffer ">= 2.1.2 < 3" ignore@^5.1.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== immer@10.0.2: version "10.0.2" @@ -3706,10 +3704,10 @@ uglify-js@^3.1.4: resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.2.tgz#319ae26a5fbd18d03c7dc02496cfa1d6f1cd4307" integrity sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ== -undici-types@~6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.13.0.tgz#e3e79220ab8c81ed1496b5812471afd7cf075ea5" - integrity sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg== +undici-types@~6.19.2: + version "6.19.6" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.6.tgz#e218c3df0987f4c0e0008ca00d6b6472d9b89b36" + integrity sha512-e/vggGopEfTKSvj4ihnOLTsqhrKRN3LeO6qSN/GxohhuRv8qH9bNQ4B8W7e/vFL+0XTnmHPB4/kegunZGA4Org== undici@^5.14.0: version "5.28.4"