@coti-io/coti-contracts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yml +52 -0
- package/CODE_OF_CONDUCT.md +44 -0
- package/CONTRIBUTING.md +101 -0
- package/LICENSE +201 -0
- package/README.md +48 -0
- package/contracts/access/DataPrivacyFramework/DataPrivacyFramework.sol +480 -0
- package/contracts/access/DataPrivacyFramework/README.md +68 -0
- package/contracts/access/DataPrivacyFramework/extensions/DataPrivacyFrameworkMpc.sol +1139 -0
- package/contracts/mocks/README.md +5 -0
- package/contracts/mocks/access/DataPrivacyFramework/DataPrivacyFrameworkMock.sol +9 -0
- package/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.sol +17 -0
- package/contracts/mocks/token/PrivateERC721/PrivateERC721URIStorageMock.sol +34 -0
- package/contracts/mocks/utils/mpc/ArithmeticTestsContract.sol +431 -0
- package/contracts/mocks/utils/mpc/BitwiseTestsContract.sol +361 -0
- package/contracts/mocks/utils/mpc/Comparison1Tests.Contract.sol +307 -0
- package/contracts/mocks/utils/mpc/Comparison2TestsContract.sol +307 -0
- package/contracts/mocks/utils/mpc/MinMaxTestsContract.sol +297 -0
- package/contracts/mocks/utils/mpc/Miscellaneous1TestsContract.sol +185 -0
- package/contracts/mocks/utils/mpc/Miscellaneous2TestsContract.sol +448 -0
- package/contracts/mocks/utils/mpc/OffboardToUserKeyTestsContract.sol +81 -0
- package/contracts/mocks/utils/mpc/README.md +486 -0
- package/contracts/mocks/utils/mpc/ShiftTestsContract.sol +311 -0
- package/contracts/mocks/utils/mpc/StringTestsContract.sol +59 -0
- package/contracts/mocks/utils/mpc/TransferScalarTestsContract.sol +271 -0
- package/contracts/mocks/utils/mpc/TransferTestsContract.sol +715 -0
- package/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.sol +25 -0
- package/contracts/onboard/AccountOnboard.sol +21 -0
- package/contracts/onboard/README.md +65 -0
- package/contracts/package.json +11 -0
- package/contracts/token/PrivateERC20/IPrivateERC20.sol +142 -0
- package/contracts/token/PrivateERC20/PrivateERC20.sol +478 -0
- package/contracts/token/PrivateERC20/README.md +104 -0
- package/contracts/token/PrivateERC721/PrivateERC721.sol +458 -0
- package/contracts/token/PrivateERC721/README.md +282 -0
- package/contracts/token/PrivateERC721/extensions/PrivateERC721URIStorage.sol +87 -0
- package/contracts/utils/mpc/MpcCore.sol +3215 -0
- package/contracts/utils/mpc/MpcInterface.sol +41 -0
- package/contracts/utils/mpc/README.md +82 -0
- package/hardhat.config.ts +18 -0
- package/package.json +14 -0
- package/test/access/DataPrivacyFramework/DataPrivacyFramework.test.ts +780 -0
- package/test/onboard/AccountOnboard.test.ts +45 -0
- package/test/token/PrivateERC20/PrivateERC20.test.ts +546 -0
- package/test/token/PrivateERC721/PrivateERC721.test.ts +223 -0
- package/test/utils/accounts.ts +55 -0
- package/test/utils/mpc/Precompile.test.ts +113 -0
- package/test/utils/mpc/String.test.ts +227 -0
- package/tsconfig.json +11 -0
- package/typechain-types/@openzeppelin/contracts/index.ts +9 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/IERC4906.ts +462 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/index.ts +6 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/IERC721.ts +393 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/IERC721Receiver.ts +110 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/token/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/utils/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/utils/introspection/ERC165.ts +94 -0
- package/typechain-types/@openzeppelin/contracts/utils/introspection/IERC165.ts +94 -0
- package/typechain-types/@openzeppelin/contracts/utils/introspection/index.ts +5 -0
- package/typechain-types/@openzeppelin/index.ts +5 -0
- package/typechain-types/common.ts +131 -0
- package/typechain-types/contracts/access/DataPrivacyFramework/DataPrivacyFramework.ts +598 -0
- package/typechain-types/contracts/access/DataPrivacyFramework/extensions/DataPrivacyFrameworkMpc.ts +598 -0
- package/typechain-types/contracts/access/DataPrivacyFramework/extensions/index.ts +4 -0
- package/typechain-types/contracts/access/DataPrivacyFramework/index.ts +6 -0
- package/typechain-types/contracts/access/index.ts +5 -0
- package/typechain-types/contracts/index.ts +13 -0
- package/typechain-types/contracts/mocks/access/DataPrivacyFramework/DataPrivacyFrameworkMock.ts +598 -0
- package/typechain-types/contracts/mocks/access/DataPrivacyFramework/index.ts +4 -0
- package/typechain-types/contracts/mocks/access/index.ts +5 -0
- package/typechain-types/contracts/mocks/index.ts +11 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.ts +543 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/index.ts +4 -0
- package/typechain-types/contracts/mocks/token/PrivateERC721/PrivateERC721URIStorageMock.ts +576 -0
- package/typechain-types/contracts/mocks/token/PrivateERC721/index.ts +4 -0
- package/typechain-types/contracts/mocks/token/index.ts +7 -0
- package/typechain-types/contracts/mocks/utils/index.ts +5 -0
- package/typechain-types/contracts/mocks/utils/mpc/ArithmeticTestsContract.ts +354 -0
- package/typechain-types/contracts/mocks/utils/mpc/BitwiseTestsContract.ts +340 -0
- package/typechain-types/contracts/mocks/utils/mpc/Comparison1Tests.Contract.sol/Comparison1TestsContract.ts +340 -0
- package/typechain-types/contracts/mocks/utils/mpc/Comparison1Tests.Contract.sol/index.ts +4 -0
- package/typechain-types/contracts/mocks/utils/mpc/Comparison2TestsContract.ts +340 -0
- package/typechain-types/contracts/mocks/utils/mpc/MinMaxTestsContract.ts +321 -0
- package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous1TestsContract.ts +199 -0
- package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous2TestsContract.ts +384 -0
- package/typechain-types/contracts/mocks/utils/mpc/OffboardToUserKeyTestsContract.sol/OffboardToUserKeyTestContract.ts +218 -0
- package/typechain-types/contracts/mocks/utils/mpc/OffboardToUserKeyTestsContract.sol/index.ts +4 -0
- package/typechain-types/contracts/mocks/utils/mpc/ShiftTestsContract.ts +339 -0
- package/typechain-types/contracts/mocks/utils/mpc/StringTestsContract.ts +211 -0
- package/typechain-types/contracts/mocks/utils/mpc/TransferScalarTestsContract.ts +266 -0
- package/typechain-types/contracts/mocks/utils/mpc/TransferTestsContract.ts +288 -0
- package/typechain-types/contracts/mocks/utils/mpc/index.ts +17 -0
- package/typechain-types/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.ts +173 -0
- package/typechain-types/contracts/mocks/wallet/PrivateERC20Wallet/index.ts +4 -0
- package/typechain-types/contracts/mocks/wallet/index.ts +5 -0
- package/typechain-types/contracts/onboard/AccountOnboard.ts +135 -0
- package/typechain-types/contracts/onboard/index.ts +4 -0
- package/typechain-types/contracts/token/PrivateERC20/IPrivateERC20.ts +437 -0
- package/typechain-types/contracts/token/PrivateERC20/PrivateERC20.ts +505 -0
- package/typechain-types/contracts/token/PrivateERC20/index.ts +5 -0
- package/typechain-types/contracts/token/PrivateERC721/PrivateERC721.ts +409 -0
- package/typechain-types/contracts/token/PrivateERC721/extensions/PrivateERC721URIStorage.ts +501 -0
- package/typechain-types/contracts/token/PrivateERC721/extensions/index.ts +4 -0
- package/typechain-types/contracts/token/PrivateERC721/index.ts +6 -0
- package/typechain-types/contracts/token/index.ts +7 -0
- package/typechain-types/contracts/utils/index.ts +5 -0
- package/typechain-types/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations.ts +698 -0
- package/typechain-types/contracts/utils/mpc/MpcInterface.sol/index.ts +4 -0
- package/typechain-types/contracts/utils/mpc/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/index.ts +6 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC4906__factory.ts +339 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors__factory.ts +127 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors__factory.ts +111 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors__factory.ts +128 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/IERC721Receiver__factory.ts +59 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/IERC721__factory.ts +307 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/ERC165__factory.ts +41 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/IERC165__factory.ts +41 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/index.ts +4 -0
- package/typechain-types/factories/contracts/access/DataPrivacyFramework/DataPrivacyFramework__factory.ts +621 -0
- package/typechain-types/factories/contracts/access/DataPrivacyFramework/extensions/DataPrivacyFrameworkMpc__factory.ts +621 -0
- package/typechain-types/factories/contracts/access/DataPrivacyFramework/extensions/index.ts +4 -0
- package/typechain-types/factories/contracts/access/DataPrivacyFramework/index.ts +5 -0
- package/typechain-types/factories/contracts/access/index.ts +4 -0
- package/typechain-types/factories/contracts/index.ts +8 -0
- package/typechain-types/factories/contracts/mocks/access/DataPrivacyFramework/DataPrivacyFrameworkMock__factory.ts +670 -0
- package/typechain-types/factories/contracts/mocks/access/DataPrivacyFramework/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/access/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/index.ts +7 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20Mock__factory.ts +615 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC721/PrivateERC721URIStorageMock__factory.ts +630 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC721/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/token/index.ts +5 -0
- package/typechain-types/factories/contracts/mocks/utils/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/ArithmeticTestsContract__factory.ts +374 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/BitwiseTestsContract__factory.ts +361 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison1Tests.Contract.sol/Comparison1TestsContract__factory.ts +361 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison1Tests.Contract.sol/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison2TestsContract__factory.ts +361 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinMaxTestsContract__factory.ts +337 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous1TestsContract__factory.ts +236 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous2TestsContract__factory.ts +432 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/OffboardToUserKeyTestsContract.sol/OffboardToUserKeyTestContract__factory.ts +245 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/OffboardToUserKeyTestsContract.sol/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/ShiftTestsContract__factory.ts +374 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/StringTestsContract__factory.ts +264 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferScalarTestsContract__factory.ts +360 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferTestsContract__factory.ts +441 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/index.ts +15 -0
- package/typechain-types/factories/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock__factory.ts +194 -0
- package/typechain-types/factories/contracts/mocks/wallet/PrivateERC20Wallet/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/wallet/index.ts +4 -0
- package/typechain-types/factories/contracts/onboard/AccountOnboard__factory.ts +104 -0
- package/typechain-types/factories/contracts/onboard/index.ts +4 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/IPrivateERC20__factory.ts +406 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/PrivateERC20__factory.ts +532 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/index.ts +5 -0
- package/typechain-types/factories/contracts/token/PrivateERC721/PrivateERC721__factory.ts +439 -0
- package/typechain-types/factories/contracts/token/PrivateERC721/extensions/PrivateERC721URIStorage__factory.ts +512 -0
- package/typechain-types/factories/contracts/token/PrivateERC721/extensions/index.ts +4 -0
- package/typechain-types/factories/contracts/token/PrivateERC721/index.ts +5 -0
- package/typechain-types/factories/contracts/token/index.ts +5 -0
- package/typechain-types/factories/contracts/utils/index.ts +4 -0
- package/typechain-types/factories/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations__factory.ts +919 -0
- package/typechain-types/factories/contracts/utils/mpc/MpcInterface.sol/index.ts +4 -0
- package/typechain-types/factories/contracts/utils/mpc/index.ts +4 -0
- package/typechain-types/factories/index.ts +5 -0
- package/typechain-types/hardhat.d.ts +621 -0
- package/typechain-types/index.ts +72 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import hre from "hardhat"
|
|
2
|
+
import { expect } from "chai"
|
|
3
|
+
|
|
4
|
+
import { generateRSAKeyPair } from "@coti-io/coti-sdk-typescript"
|
|
5
|
+
import { setupAccounts } from "../utils/accounts"
|
|
6
|
+
|
|
7
|
+
const gasLimit = 12000000
|
|
8
|
+
|
|
9
|
+
async function deploy() {
|
|
10
|
+
const [owner, otherAccount] = await setupAccounts()
|
|
11
|
+
|
|
12
|
+
const factory = await hre.ethers.getContractFactory("AccountOnboard")
|
|
13
|
+
const contract = await factory.connect(owner).deploy({ gasLimit })
|
|
14
|
+
await contract.waitForDeployment()
|
|
15
|
+
|
|
16
|
+
return { contract, contractAddress: await contract.getAddress(), owner, otherAccount }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("Account Onboard", function () {
|
|
20
|
+
let deployment: Awaited<ReturnType<typeof deploy>>
|
|
21
|
+
|
|
22
|
+
before(async function () {
|
|
23
|
+
deployment = await deploy()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('Should successfully onboard the account', async function () {
|
|
27
|
+
const { owner } = deployment
|
|
28
|
+
|
|
29
|
+
await owner.generateOrRecoverAes()
|
|
30
|
+
|
|
31
|
+
expect(owner.getUserOnboardInfo()?.aesKey).to.not.equal('')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('Should revert when the signature is empty', async function () {
|
|
35
|
+
const { owner, contract } = deployment
|
|
36
|
+
|
|
37
|
+
const { publicKey } = generateRSAKeyPair()
|
|
38
|
+
|
|
39
|
+
const tx = await contract
|
|
40
|
+
.connect(owner)
|
|
41
|
+
.onboardAccount(publicKey, '0x')
|
|
42
|
+
|
|
43
|
+
expect(tx).to.be.reverted
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import hre from "hardhat"
|
|
2
|
+
import { expect } from "chai"
|
|
3
|
+
|
|
4
|
+
import { setupAccounts } from "../../utils/accounts"
|
|
5
|
+
import { PrivateERC20Mock, PrivateERC20WalletMock } from "../../../typechain-types"
|
|
6
|
+
import { itUint, Wallet, ZeroAddress } from "@coti-io/coti-ethers"
|
|
7
|
+
|
|
8
|
+
const GAS_LIMIT = 12000000
|
|
9
|
+
|
|
10
|
+
async function deploy() {
|
|
11
|
+
const [owner, otherAccount] = await setupAccounts()
|
|
12
|
+
|
|
13
|
+
const tokenContract = await hre.ethers.getContractFactory("PrivateERC20Mock")
|
|
14
|
+
|
|
15
|
+
const token = await tokenContract
|
|
16
|
+
.connect(owner)
|
|
17
|
+
.deploy({ gasLimit: GAS_LIMIT })
|
|
18
|
+
|
|
19
|
+
const contract = await token.waitForDeployment()
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
contract,
|
|
23
|
+
contractAddress: await contract.getAddress(),
|
|
24
|
+
owner,
|
|
25
|
+
otherAccount
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("Private ERC20", function () {
|
|
30
|
+
let contract: PrivateERC20Mock
|
|
31
|
+
let contractAddress: string
|
|
32
|
+
let owner: Wallet
|
|
33
|
+
let otherAccount: Wallet
|
|
34
|
+
|
|
35
|
+
before(async function () {
|
|
36
|
+
const deployment = await deploy()
|
|
37
|
+
|
|
38
|
+
contract = deployment.contract
|
|
39
|
+
contractAddress = deployment.contractAddress
|
|
40
|
+
owner = deployment.owner
|
|
41
|
+
otherAccount = deployment.otherAccount
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
describe("deploy", function () {
|
|
45
|
+
it('has a name', async function () {
|
|
46
|
+
await expect(await contract.name()).to.equal("PrivateERC20Mock");
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('has a symbol', async function () {
|
|
50
|
+
await expect(await contract.symbol()).to.equal("PE20M");
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('has 2 decimals', async function () {
|
|
54
|
+
await expect(await contract.decimals()).to.equal(2n);
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe("mint", function () {
|
|
59
|
+
const value = 5000n
|
|
60
|
+
|
|
61
|
+
describe("successful mint", async function () {
|
|
62
|
+
before("minting", async function () {
|
|
63
|
+
this.tx = await contract
|
|
64
|
+
.connect(owner)
|
|
65
|
+
.mint(owner.address, value, { gasLimit: GAS_LIMIT })
|
|
66
|
+
|
|
67
|
+
await this.tx.wait()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('does not increment totalSupply', async function () {
|
|
71
|
+
await expect(await contract.totalSupply()).to.equal(0n)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('increments recipient balance', async function () {
|
|
75
|
+
const ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
76
|
+
|
|
77
|
+
const balance = await owner.decryptValue(ctBalance)
|
|
78
|
+
|
|
79
|
+
await expect(balance).to.equal(value)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('emits Transfer event', async function () {
|
|
83
|
+
await expect(this.tx).to.emit(contract, "Transfer")
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
describe('failed mint', async function () {
|
|
88
|
+
it('rejects minting to the zero address', async function () {
|
|
89
|
+
await expect(
|
|
90
|
+
contract
|
|
91
|
+
.connect(owner)
|
|
92
|
+
.mint(ZeroAddress, value)
|
|
93
|
+
)
|
|
94
|
+
.to.be.revertedWithCustomError(contract, "ERC20InvalidReceiver")
|
|
95
|
+
.withArgs(ZeroAddress)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// it('rejects overflow', async function () {
|
|
99
|
+
// const tx = await contract
|
|
100
|
+
// .connect(owner.wallet)
|
|
101
|
+
// .mint(owner.wallet.address, (BigInt(2) ** BigInt(64)) - BigInt(1), { gasLimit: GAS_LIMIT })
|
|
102
|
+
|
|
103
|
+
// await tx.wait()
|
|
104
|
+
|
|
105
|
+
// await expect(tx).to.be.reverted
|
|
106
|
+
// })
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
describe("burn", function () {
|
|
111
|
+
const value = 5000n
|
|
112
|
+
|
|
113
|
+
describe('failed burn', async function () {
|
|
114
|
+
it('rejects burning from the zero address', async function () {
|
|
115
|
+
await expect(
|
|
116
|
+
contract
|
|
117
|
+
.connect(owner)
|
|
118
|
+
.burn(ZeroAddress, value)
|
|
119
|
+
)
|
|
120
|
+
.to.be.revertedWithCustomError(contract, "ERC20InvalidSender")
|
|
121
|
+
.withArgs(ZeroAddress)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('does not update balance when burning more than balance', async function () {
|
|
125
|
+
const tx = await contract
|
|
126
|
+
.connect(owner)
|
|
127
|
+
.burn(owner.address, value + 1n, { gasLimit: GAS_LIMIT })
|
|
128
|
+
|
|
129
|
+
await tx.wait()
|
|
130
|
+
|
|
131
|
+
const ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
132
|
+
|
|
133
|
+
const balance = await owner.decryptValue(ctBalance)
|
|
134
|
+
|
|
135
|
+
await expect(balance).to.equal(value)
|
|
136
|
+
})
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
describe('successful burn', async function () {
|
|
140
|
+
before("burning", async function () {
|
|
141
|
+
this.tx = await contract
|
|
142
|
+
.connect(owner)
|
|
143
|
+
.burn(owner.address, value, { gasLimit: GAS_LIMIT })
|
|
144
|
+
|
|
145
|
+
await this.tx.wait()
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('decrements the senders balance', async function () {
|
|
149
|
+
const ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
150
|
+
|
|
151
|
+
const balance = await owner.decryptValue(ctBalance)
|
|
152
|
+
|
|
153
|
+
await expect(balance).to.equal(0n)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('emits Transfer event', async function () {
|
|
157
|
+
await expect(this.tx).to.emit(contract, "Transfer")
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
describe("transfer", function () {
|
|
163
|
+
const value = 10000n
|
|
164
|
+
|
|
165
|
+
before("minting", async function () {
|
|
166
|
+
this.tx = await contract
|
|
167
|
+
.connect(owner)
|
|
168
|
+
.mint(owner.address, value, { gasLimit: GAS_LIMIT })
|
|
169
|
+
|
|
170
|
+
await this.tx.wait()
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
describe("failed transfer", async function () {
|
|
174
|
+
it('rejects transferring to the zero address', async function () {
|
|
175
|
+
const itValue = await owner.encryptValue(value, contractAddress, contract["transfer(address,(uint256,bytes))"].fragment.selector) as itUint
|
|
176
|
+
|
|
177
|
+
await expect(
|
|
178
|
+
contract
|
|
179
|
+
.connect(owner)
|
|
180
|
+
["transfer(address,(uint256,bytes))"]
|
|
181
|
+
(ZeroAddress, itValue)
|
|
182
|
+
)
|
|
183
|
+
.to.be.revertedWithCustomError(contract, "ERC20InvalidReceiver")
|
|
184
|
+
.withArgs(ZeroAddress)
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('does not transfer tokens when amount exceeds balance', async function () {
|
|
188
|
+
const itValue = await owner.encryptValue(value + 1n, contractAddress, contract["transfer(address,(uint256,bytes))"].fragment.selector) as itUint
|
|
189
|
+
|
|
190
|
+
const tx = await contract
|
|
191
|
+
.connect(owner)
|
|
192
|
+
["transfer(address,(uint256,bytes))"]
|
|
193
|
+
(otherAccount.address, itValue, { gasLimit: GAS_LIMIT })
|
|
194
|
+
|
|
195
|
+
await tx.wait()
|
|
196
|
+
|
|
197
|
+
let ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
198
|
+
|
|
199
|
+
let balance = await owner.decryptValue(ctBalance)
|
|
200
|
+
|
|
201
|
+
await expect(balance).to.equal(value)
|
|
202
|
+
|
|
203
|
+
ctBalance = await contract["balanceOf(address)"](otherAccount.address)
|
|
204
|
+
|
|
205
|
+
balance = await otherAccount.decryptValue(ctBalance)
|
|
206
|
+
|
|
207
|
+
await expect(balance).to.equal(0n)
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
describe("successful transfer", async function () {
|
|
212
|
+
before("transferring", async function () {
|
|
213
|
+
const itValue = await owner.encryptValue(value / 2n, contractAddress, contract["transfer(address,(uint256,bytes))"].fragment.selector) as itUint
|
|
214
|
+
|
|
215
|
+
const tx = await contract
|
|
216
|
+
.connect(owner)
|
|
217
|
+
["transfer(address,(uint256,bytes))"]
|
|
218
|
+
(otherAccount.address, itValue, { gasLimit: GAS_LIMIT })
|
|
219
|
+
|
|
220
|
+
await tx.wait()
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
it('decrements the senders balance', async function () {
|
|
224
|
+
const ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
225
|
+
|
|
226
|
+
const balance = await owner.decryptValue(ctBalance)
|
|
227
|
+
|
|
228
|
+
await expect(balance).to.equal(value / 2n)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
it('increments the receivers balance', async function () {
|
|
232
|
+
const ctBalance = await contract["balanceOf(address)"](otherAccount.address)
|
|
233
|
+
|
|
234
|
+
const balance = await otherAccount.decryptValue(ctBalance)
|
|
235
|
+
|
|
236
|
+
await expect(balance).to.equal(value / 2n)
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
describe("approve", function () {
|
|
242
|
+
const value = 5000n
|
|
243
|
+
|
|
244
|
+
describe("failed approval", async function () {
|
|
245
|
+
it('rejects when approving the zero address', async function () {
|
|
246
|
+
const itValue = await owner.encryptValue(value, contractAddress, contract["transfer(address,(uint256,bytes))"].fragment.selector) as itUint
|
|
247
|
+
|
|
248
|
+
await expect(
|
|
249
|
+
contract
|
|
250
|
+
.connect(owner)
|
|
251
|
+
["approve(address,(uint256,bytes))"]
|
|
252
|
+
(ZeroAddress, itValue)
|
|
253
|
+
)
|
|
254
|
+
.to.be.revertedWithCustomError(contract, "ERC20InvalidSpender")
|
|
255
|
+
.withArgs(ZeroAddress)
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
describe("successful approval", async function () {
|
|
260
|
+
before('approving', async function () {
|
|
261
|
+
const itValue = await owner.encryptValue(value, contractAddress, contract["approve(address,(uint256,bytes))"].fragment.selector) as itUint
|
|
262
|
+
|
|
263
|
+
const tx = await contract
|
|
264
|
+
.connect(owner)
|
|
265
|
+
["approve(address,(uint256,bytes))"]
|
|
266
|
+
(otherAccount.address, itValue, { gasLimit: GAS_LIMIT })
|
|
267
|
+
|
|
268
|
+
await tx.wait()
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
it('increment the allowance encrypted with the owners key', async function () {
|
|
272
|
+
const ctAllowance = await contract
|
|
273
|
+
["allowance(address,address)"]
|
|
274
|
+
(owner.address, otherAccount.address)
|
|
275
|
+
|
|
276
|
+
const allowance = await owner.decryptValue(ctAllowance[1])
|
|
277
|
+
|
|
278
|
+
await expect(allowance).to.equal(value)
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
it('increment the allowance encrypted with the spenders key', async function () {
|
|
282
|
+
const ctAllowance = await contract
|
|
283
|
+
["allowance(address,address)"]
|
|
284
|
+
(owner.address, otherAccount.address)
|
|
285
|
+
|
|
286
|
+
const allowance = await otherAccount.decryptValue(ctAllowance[2])
|
|
287
|
+
|
|
288
|
+
await expect(allowance).to.equal(value)
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
describe('transferFrom', function () {
|
|
294
|
+
const value = 3000n
|
|
295
|
+
|
|
296
|
+
describe('failed transferFrom', async function () {
|
|
297
|
+
it('rejects transferring to the zero address', async function () {
|
|
298
|
+
const itValue = await otherAccount.encryptValue(value, contractAddress, contract["transferFrom(address,address,(uint256,bytes))"].fragment.selector)as itUint
|
|
299
|
+
|
|
300
|
+
await expect(
|
|
301
|
+
contract
|
|
302
|
+
.connect(otherAccount)
|
|
303
|
+
["transferFrom(address,address,(uint256,bytes))"]
|
|
304
|
+
(owner.address, ZeroAddress, itValue)
|
|
305
|
+
)
|
|
306
|
+
.to.be.revertedWithCustomError(contract, "ERC20InvalidReceiver")
|
|
307
|
+
.withArgs(ZeroAddress)
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
describe("transferring more than the owners balance", async function () {
|
|
311
|
+
before("transferring", async function () {
|
|
312
|
+
const itValue = await otherAccount.encryptValue(2n * value, contractAddress, contract["transferFrom(address,address,(uint256,bytes))"].fragment.selector)as itUint
|
|
313
|
+
|
|
314
|
+
const tx = await contract
|
|
315
|
+
.connect(otherAccount)
|
|
316
|
+
["transferFrom(address,address,(uint256,bytes))"]
|
|
317
|
+
(owner.address, "0x0000000000000000000000000000000000000001", itValue)
|
|
318
|
+
|
|
319
|
+
await tx.wait()
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
it("does not decrement the owners balance", async function () {
|
|
323
|
+
const ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
324
|
+
|
|
325
|
+
const balance = await owner.decryptValue(ctBalance)
|
|
326
|
+
|
|
327
|
+
await expect(balance).to.equal(5000n)
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it("does not decrement the spenders allowance", async function () {
|
|
331
|
+
const ctAllowance = await contract["allowance(address,address)"](owner.address, otherAccount.address)
|
|
332
|
+
|
|
333
|
+
const allowance = await owner.decryptValue(ctAllowance[1])
|
|
334
|
+
|
|
335
|
+
await expect(allowance).to.equal(5000n)
|
|
336
|
+
})
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
describe('successful transferFrom', async function () {
|
|
341
|
+
before('transferring', async function () {
|
|
342
|
+
const itValue = await otherAccount.encryptValue(value, contractAddress, contract["transferFrom(address,address,(uint256,bytes))"].fragment.selector)as itUint
|
|
343
|
+
|
|
344
|
+
const tx = await contract
|
|
345
|
+
.connect(otherAccount)
|
|
346
|
+
["transferFrom(address,address,(uint256,bytes))"]
|
|
347
|
+
(owner.address, otherAccount.address, itValue)
|
|
348
|
+
|
|
349
|
+
await tx.wait()
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
it('decrement the owners balance', async function () {
|
|
353
|
+
const ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
354
|
+
|
|
355
|
+
const balance = await owner.decryptValue(ctBalance)
|
|
356
|
+
|
|
357
|
+
await expect(balance).to.equal(2000n)
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it('increment the recipients balance', async function () {
|
|
361
|
+
const ctBalance = await contract["balanceOf(address)"](otherAccount.address)
|
|
362
|
+
|
|
363
|
+
const balance = await otherAccount.decryptValue(ctBalance)
|
|
364
|
+
|
|
365
|
+
await expect(balance).to.equal(8000n)
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
it('decrement the spenders allowance', async function () {
|
|
369
|
+
const ctAllowance = await contract["allowance(address,address)"](owner.address, otherAccount.address)
|
|
370
|
+
|
|
371
|
+
const allowance = await otherAccount.decryptValue(ctAllowance[2])
|
|
372
|
+
|
|
373
|
+
await expect(allowance).to.equal(2000n)
|
|
374
|
+
})
|
|
375
|
+
})
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
describe("contract-to-contract interactions", function () {
|
|
379
|
+
const value = 10000n
|
|
380
|
+
let walletContract: PrivateERC20WalletMock
|
|
381
|
+
let walletContractAddress: string
|
|
382
|
+
|
|
383
|
+
before("deploying and funding wallet contract", async function () {
|
|
384
|
+
const walletContractFactory = await hre.ethers.getContractFactory("PrivateERC20WalletMock")
|
|
385
|
+
|
|
386
|
+
walletContract = await walletContractFactory
|
|
387
|
+
.connect(owner)
|
|
388
|
+
.deploy({ gasLimit: GAS_LIMIT })
|
|
389
|
+
|
|
390
|
+
walletContract = await walletContract.waitForDeployment()
|
|
391
|
+
|
|
392
|
+
walletContractAddress = await walletContract.getAddress()
|
|
393
|
+
|
|
394
|
+
this.tx = await contract
|
|
395
|
+
.connect(owner)
|
|
396
|
+
.mint(walletContractAddress, value, { gasLimit: GAS_LIMIT })
|
|
397
|
+
|
|
398
|
+
await this.tx.wait()
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
describe("setAccountEncryptionAddress", async function () {
|
|
402
|
+
before("setting account encryption address", async function () {
|
|
403
|
+
const tx = await walletContract
|
|
404
|
+
.connect(otherAccount)
|
|
405
|
+
.setAccountEncryptionAddress(contractAddress, otherAccount.address, { gasLimit: GAS_LIMIT })
|
|
406
|
+
|
|
407
|
+
await tx.wait()
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
it("update accountEncryptionAddress mapping", async function () {
|
|
411
|
+
const accountEncryptionAddress = await contract.accountEncryptionAddress(walletContractAddress)
|
|
412
|
+
|
|
413
|
+
await expect(accountEncryptionAddress).to.equal(otherAccount.address)
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
it("reencrypt balance using the new account encryption address", async function () {
|
|
417
|
+
const ctBalance = await contract["balanceOf(address)"](walletContractAddress)
|
|
418
|
+
|
|
419
|
+
const balance = await otherAccount.decryptValue(ctBalance)
|
|
420
|
+
|
|
421
|
+
await expect(balance).to.equal(value)
|
|
422
|
+
})
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
describe("transfer", async function () {
|
|
426
|
+
before("transferring", async function () {
|
|
427
|
+
const tx = await walletContract
|
|
428
|
+
.connect(otherAccount)
|
|
429
|
+
.transfer(contractAddress, otherAccount.address, value / 2n, { gasLimit: GAS_LIMIT })
|
|
430
|
+
|
|
431
|
+
await tx.wait()
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
it('decrement the senders balance', async function () {
|
|
435
|
+
const ctBalance = await contract["balanceOf(address)"](walletContractAddress)
|
|
436
|
+
|
|
437
|
+
const balance = await otherAccount.decryptValue(ctBalance)
|
|
438
|
+
|
|
439
|
+
await expect(balance).to.equal(value / 2n)
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
it('increment the receivers balance', async function () {
|
|
443
|
+
const ctBalance = await contract["balanceOf(address)"](otherAccount.address)
|
|
444
|
+
|
|
445
|
+
const balance = await otherAccount.decryptValue(ctBalance)
|
|
446
|
+
|
|
447
|
+
await expect(balance).to.equal(13000n)
|
|
448
|
+
})
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
describe("approve", async function () {
|
|
452
|
+
before("approving", async function () {
|
|
453
|
+
const tx = await walletContract
|
|
454
|
+
.connect(otherAccount)
|
|
455
|
+
.approve(contractAddress, owner.address, value / 2n, { gasLimit: GAS_LIMIT })
|
|
456
|
+
|
|
457
|
+
await tx.wait()
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
it("increment the spenders allowance", async function () {
|
|
461
|
+
const ctAllowance = await contract["allowance(address,address)"](walletContractAddress, owner.address)
|
|
462
|
+
|
|
463
|
+
const allowance = await otherAccount.decryptValue(ctAllowance[1])
|
|
464
|
+
|
|
465
|
+
await expect(allowance).to.equal(value / 2n)
|
|
466
|
+
})
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
describe("transferFrom", async function () {
|
|
470
|
+
const value = 5000n
|
|
471
|
+
|
|
472
|
+
before("transferring", async function () {
|
|
473
|
+
const itValue = await otherAccount.encryptValue(value, contractAddress, contract["approve(address,(uint256,bytes))"].fragment.selector) as itUint
|
|
474
|
+
|
|
475
|
+
let tx = await contract
|
|
476
|
+
.connect(otherAccount)
|
|
477
|
+
["approve(address,(uint256,bytes))"]
|
|
478
|
+
(walletContractAddress, itValue)
|
|
479
|
+
|
|
480
|
+
await tx.wait()
|
|
481
|
+
|
|
482
|
+
tx = await walletContract
|
|
483
|
+
.connect(otherAccount)
|
|
484
|
+
.transferFrom(contractAddress, otherAccount.address, owner.address, value)
|
|
485
|
+
|
|
486
|
+
await tx.wait()
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
it('decrement the owners balance', async function () {
|
|
490
|
+
const itBalance = await contract["balanceOf(address)"](otherAccount.address)
|
|
491
|
+
|
|
492
|
+
const balance = await otherAccount.decryptValue(itBalance)
|
|
493
|
+
|
|
494
|
+
await expect(balance).to.equal(8000n)
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
it('increment the recipients balance', async function () {
|
|
498
|
+
const itBalance = await contract["balanceOf(address)"](owner.address)
|
|
499
|
+
|
|
500
|
+
const balance = await owner.decryptValue(itBalance)
|
|
501
|
+
|
|
502
|
+
await expect(balance).to.equal(7000n)
|
|
503
|
+
})
|
|
504
|
+
})
|
|
505
|
+
})
|
|
506
|
+
|
|
507
|
+
describe("maximum allowance", function () {
|
|
508
|
+
const value = (2n ** 64n) - 1n
|
|
509
|
+
|
|
510
|
+
before("transferring", async function () {
|
|
511
|
+
let itValue = await owner.encryptValue(value, contractAddress, contract["approve(address,(uint256,bytes))"].fragment.selector) as itUint
|
|
512
|
+
|
|
513
|
+
let tx = await contract
|
|
514
|
+
.connect(owner)
|
|
515
|
+
["approve(address,(uint256,bytes))"]
|
|
516
|
+
(otherAccount.address, itValue)
|
|
517
|
+
|
|
518
|
+
await tx.wait()
|
|
519
|
+
|
|
520
|
+
itValue = await otherAccount.encryptValue(7000n, contractAddress, contract["transferFrom(address,address,(uint256,bytes))"].fragment.selector) as itUint
|
|
521
|
+
|
|
522
|
+
tx = await contract
|
|
523
|
+
.connect(otherAccount)
|
|
524
|
+
["transferFrom(address,address,(uint256,bytes))"]
|
|
525
|
+
(owner.address, "0x0000000000000000000000000000000000000001", itValue)
|
|
526
|
+
|
|
527
|
+
await tx.wait()
|
|
528
|
+
})
|
|
529
|
+
|
|
530
|
+
it("decrement the owners balance", async function () {
|
|
531
|
+
const ctBalance = await contract["balanceOf(address)"](owner.address)
|
|
532
|
+
|
|
533
|
+
const balance = await owner.decryptValue(ctBalance)
|
|
534
|
+
|
|
535
|
+
await expect(balance).to.equal(0n)
|
|
536
|
+
})
|
|
537
|
+
|
|
538
|
+
it("does not decrement the spenders allowance", async function () {
|
|
539
|
+
const ctAllowance = await contract["allowance(address,address)"](owner.address, otherAccount.address)
|
|
540
|
+
|
|
541
|
+
const allowance = await owner.decryptValue(ctAllowance[1])
|
|
542
|
+
|
|
543
|
+
await expect(allowance).to.equal(value)
|
|
544
|
+
})
|
|
545
|
+
})
|
|
546
|
+
})
|