@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,478 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity ^0.8.19;
|
|
4
|
+
|
|
5
|
+
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
|
|
6
|
+
import {IPrivateERC20} from "./IPrivateERC20.sol";
|
|
7
|
+
import "../../utils/mpc/MpcCore.sol";
|
|
8
|
+
|
|
9
|
+
abstract contract PrivateERC20 is Context, IPrivateERC20 {
|
|
10
|
+
uint64 private constant MAX_UINT_64 = type(uint64).max;
|
|
11
|
+
|
|
12
|
+
mapping(address account => address) private _accountEncryptionAddress;
|
|
13
|
+
|
|
14
|
+
mapping(address account => utUint64) private _balances;
|
|
15
|
+
|
|
16
|
+
mapping(address account => mapping(address spender => Allowance)) private _allowances;
|
|
17
|
+
|
|
18
|
+
ctUint64 private _totalSupply;
|
|
19
|
+
|
|
20
|
+
string private _name;
|
|
21
|
+
|
|
22
|
+
string private _symbol;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @dev Indicates a failure with the token `sender`. Used in transfers.
|
|
26
|
+
* @param sender Address whose tokens are being transferred.
|
|
27
|
+
*/
|
|
28
|
+
error ERC20InvalidSender(address sender);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @dev Indicates a failure with the token `receiver`. Used in transfers.
|
|
32
|
+
* @param receiver Address to which tokens are being transferred.
|
|
33
|
+
*/
|
|
34
|
+
error ERC20InvalidReceiver(address receiver);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
|
|
38
|
+
* @param approver Address initiating an approval operation.
|
|
39
|
+
*/
|
|
40
|
+
error ERC20InvalidApprover(address approver);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
|
|
44
|
+
* @param spender Address that may be allowed to operate on tokens without being their owner.
|
|
45
|
+
*/
|
|
46
|
+
error ERC20InvalidSpender(address spender);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @dev Sets the values for {name} and {symbol}.
|
|
50
|
+
*
|
|
51
|
+
* All two of these values are immutable: they can only be set once during
|
|
52
|
+
* construction.
|
|
53
|
+
*/
|
|
54
|
+
constructor(string memory name_, string memory symbol_) {
|
|
55
|
+
_name = name_;
|
|
56
|
+
_symbol = symbol_;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @dev Returns the name of the token.
|
|
61
|
+
*/
|
|
62
|
+
function name() public view virtual returns (string memory) {
|
|
63
|
+
return _name;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @dev Returns the symbol of the token, usually a shorter version of the
|
|
68
|
+
* name.
|
|
69
|
+
*/
|
|
70
|
+
function symbol() public view virtual returns (string memory) {
|
|
71
|
+
return _symbol;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @dev Returns the number of decimals used to get its user representation.
|
|
76
|
+
* For example, if `decimals` equals `2`, a balance of `505` tokens should
|
|
77
|
+
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
|
|
78
|
+
*
|
|
79
|
+
* Tokens usually opt for a value of 18, imitating the relationship between
|
|
80
|
+
* Ether and Wei. This is the default value returned by this function, unless
|
|
81
|
+
* it's overridden.
|
|
82
|
+
*
|
|
83
|
+
* NOTE: This information is only used for _display_ purposes: it in
|
|
84
|
+
* no way affects any of the arithmetic of the contract, including
|
|
85
|
+
* {IPrivateERC20-balanceOf} and {IPrivateERC20-transfer}.
|
|
86
|
+
*/
|
|
87
|
+
function decimals() public view virtual returns (uint8) {
|
|
88
|
+
return 2;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @dev See {IPrivateERC20-totalSupply}.
|
|
93
|
+
*/
|
|
94
|
+
function totalSupply() public view virtual returns (uint256) {
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function accountEncryptionAddress(address account) public view returns (address) {
|
|
99
|
+
return _accountEncryptionAddress[account];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @dev See {IPrivateERC20-balanceOf}.
|
|
104
|
+
*/
|
|
105
|
+
function balanceOf(address account) public view virtual returns (ctUint64) {
|
|
106
|
+
return _balances[account].userCiphertext;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @dev See {IPrivateERC20-balanceOf}.
|
|
111
|
+
*/
|
|
112
|
+
function balanceOf() public virtual returns (gtUint64) {
|
|
113
|
+
return _getBalance(_msgSender());
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @dev See {IPrivateERC20-setAccountEncryptionAddress}.
|
|
118
|
+
*
|
|
119
|
+
* NOTE: This will not reencrypt your allowances until they are changed
|
|
120
|
+
*/
|
|
121
|
+
function setAccountEncryptionAddress(address offBoardAddress) public virtual returns (bool) {
|
|
122
|
+
gtUint64 gtBalance = _getBalance(_msgSender());
|
|
123
|
+
|
|
124
|
+
_accountEncryptionAddress[_msgSender()] = offBoardAddress;
|
|
125
|
+
|
|
126
|
+
_balances[_msgSender()].userCiphertext = MpcCore.offBoardToUser(gtBalance, offBoardAddress);
|
|
127
|
+
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @dev See {IPrivateERC20-transfer}.
|
|
133
|
+
*
|
|
134
|
+
* Requirements:
|
|
135
|
+
*
|
|
136
|
+
* - `to` cannot be the zero address.
|
|
137
|
+
* - the caller must have a balance of at least `value`.
|
|
138
|
+
*/
|
|
139
|
+
function transfer(address to, itUint64 calldata value) public virtual returns (gtBool) {
|
|
140
|
+
address owner = _msgSender();
|
|
141
|
+
|
|
142
|
+
gtUint64 gtValue = MpcCore.validateCiphertext(value);
|
|
143
|
+
|
|
144
|
+
return _transfer(owner, to, gtValue);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @dev See {IPrivateERC20-transfer}.
|
|
149
|
+
*
|
|
150
|
+
* Requirements:
|
|
151
|
+
*
|
|
152
|
+
* - `to` cannot be the zero address.
|
|
153
|
+
* - the caller must have a balance of at least `value`.
|
|
154
|
+
*/
|
|
155
|
+
function transfer(address to, gtUint64 value) public virtual returns (gtBool) {
|
|
156
|
+
address owner = _msgSender();
|
|
157
|
+
|
|
158
|
+
return _transfer(owner, to, value);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @dev See {IPrivateERC20-allowance}.
|
|
163
|
+
*/
|
|
164
|
+
function allowance(address owner, address spender) public view virtual returns (Allowance memory) {
|
|
165
|
+
return _allowances[owner][spender];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @dev See {IPrivateERC20-allowance}.
|
|
170
|
+
*/
|
|
171
|
+
function allowance(address account, bool isSpender) public virtual returns (gtUint64) {
|
|
172
|
+
if (isSpender) {
|
|
173
|
+
return _safeOnboard(_allowances[_msgSender()][account].ciphertext);
|
|
174
|
+
} else {
|
|
175
|
+
return _safeOnboard(_allowances[account][_msgSender()].ciphertext);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function reencryptAllowance(address account, bool isSpender) public virtual returns (bool) {
|
|
180
|
+
address encryptionAddress = _getAccountEncryptionAddress(_msgSender());
|
|
181
|
+
|
|
182
|
+
if (isSpender) {
|
|
183
|
+
Allowance storage allowance_ = _allowances[_msgSender()][account];
|
|
184
|
+
|
|
185
|
+
allowance_.ownerCiphertext = MpcCore.offBoardToUser(
|
|
186
|
+
_safeOnboard(allowance_.ciphertext),
|
|
187
|
+
encryptionAddress
|
|
188
|
+
);
|
|
189
|
+
} else {
|
|
190
|
+
Allowance storage allowance_ = _allowances[account][_msgSender()];
|
|
191
|
+
|
|
192
|
+
allowance_.spenderCiphertext = MpcCore.offBoardToUser(
|
|
193
|
+
_safeOnboard(allowance_.ciphertext),
|
|
194
|
+
encryptionAddress
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @dev See {IPrivateERC20-approve}.
|
|
203
|
+
*
|
|
204
|
+
* NOTE: If `value` is the maximum `itUint64`, the allowance is not updated on
|
|
205
|
+
* `transferFrom`. This is semantically equivalent to an infinite approval.
|
|
206
|
+
*
|
|
207
|
+
* Requirements:
|
|
208
|
+
*
|
|
209
|
+
* - `spender` cannot be the zero address.
|
|
210
|
+
*/
|
|
211
|
+
function approve(address spender, itUint64 calldata value) public virtual returns (bool) {
|
|
212
|
+
address owner = _msgSender();
|
|
213
|
+
|
|
214
|
+
gtUint64 gtValue = MpcCore.validateCiphertext(value);
|
|
215
|
+
|
|
216
|
+
_approve(owner, spender, gtValue);
|
|
217
|
+
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @dev See {IPrivateERC20-approve}.
|
|
223
|
+
*
|
|
224
|
+
* NOTE: If `value` is the maximum `gtUint64`, the allowance is not updated on
|
|
225
|
+
* `transferFrom`. This is semantically equivalent to an infinite approval.
|
|
226
|
+
*
|
|
227
|
+
* Requirements:
|
|
228
|
+
*
|
|
229
|
+
* - `spender` cannot be the zero address.
|
|
230
|
+
*/
|
|
231
|
+
function approve(address spender, gtUint64 value) public virtual returns (bool) {
|
|
232
|
+
address owner = _msgSender();
|
|
233
|
+
|
|
234
|
+
_approve(owner, spender, value);
|
|
235
|
+
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @dev See {IPrivateERC20-transferFrom}.
|
|
241
|
+
*
|
|
242
|
+
* Requirements:
|
|
243
|
+
*
|
|
244
|
+
* - `from` and `to` cannot be the zero address.
|
|
245
|
+
* - `from` must have a balance of at least `value`.
|
|
246
|
+
* - the caller must have allowance for ``from``'s tokens of at least
|
|
247
|
+
* `value`.
|
|
248
|
+
*/
|
|
249
|
+
function transferFrom(address from, address to, itUint64 calldata value) public virtual returns (gtBool) {
|
|
250
|
+
address spender = _msgSender();
|
|
251
|
+
|
|
252
|
+
gtUint64 gtValue = MpcCore.validateCiphertext(value);
|
|
253
|
+
|
|
254
|
+
_spendAllowance(from, spender, gtValue);
|
|
255
|
+
|
|
256
|
+
return _transfer(from, to, gtValue);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @dev See {IPrivateERC20-transferFrom}.
|
|
261
|
+
*
|
|
262
|
+
* Requirements:
|
|
263
|
+
*
|
|
264
|
+
* - `from` and `to` cannot be the zero address.
|
|
265
|
+
* - `from` must have a balance of at least `value`.
|
|
266
|
+
* - the caller must have allowance for ``from``'s tokens of at least
|
|
267
|
+
* `value`.
|
|
268
|
+
*/
|
|
269
|
+
function transferFrom(address from, address to, gtUint64 value) public virtual returns (gtBool) {
|
|
270
|
+
address spender = _msgSender();
|
|
271
|
+
|
|
272
|
+
_spendAllowance(from, spender, value);
|
|
273
|
+
|
|
274
|
+
return _transfer(from, to, value);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* @dev Moves a `value` amount of tokens from `from` to `to`.
|
|
279
|
+
*
|
|
280
|
+
* This internal function is equivalent to {transfer}, and can be used to
|
|
281
|
+
* e.g. implement automatic token fees, slashing mechanisms, etc.
|
|
282
|
+
*
|
|
283
|
+
* Emits a {Transfer} event.
|
|
284
|
+
*
|
|
285
|
+
* NOTE: This function is not virtual, {_update} should be overridden instead.
|
|
286
|
+
*/
|
|
287
|
+
function _transfer(address from, address to, gtUint64 value) internal returns (gtBool) {
|
|
288
|
+
if (from == address(0)) {
|
|
289
|
+
revert ERC20InvalidSender(address(0));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (to == address(0)) {
|
|
293
|
+
revert ERC20InvalidReceiver(address(0));
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return _update(from, to, value);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
|
|
301
|
+
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
|
|
302
|
+
* this function.
|
|
303
|
+
*
|
|
304
|
+
* Emits a {Transfer} event.
|
|
305
|
+
*/
|
|
306
|
+
function _update(address from, address to, gtUint64 value) internal virtual returns (gtBool) {
|
|
307
|
+
gtUint64 newToBalance;
|
|
308
|
+
gtUint64 valueTransferred = value;
|
|
309
|
+
gtBool result = MpcCore.setPublic(true);
|
|
310
|
+
|
|
311
|
+
if (from == address(0)) {
|
|
312
|
+
gtUint64 totalSupply_ = _safeOnboard(_totalSupply);
|
|
313
|
+
|
|
314
|
+
totalSupply_ = MpcCore.add(totalSupply_, value);
|
|
315
|
+
|
|
316
|
+
_totalSupply = MpcCore.offBoard(totalSupply_);
|
|
317
|
+
|
|
318
|
+
gtUint64 currentBalance = _getBalance(to);
|
|
319
|
+
|
|
320
|
+
newToBalance = MpcCore.add(currentBalance, value);
|
|
321
|
+
} else {
|
|
322
|
+
gtUint64 fromBalance = _getBalance(from);
|
|
323
|
+
gtUint64 toBalance = _getBalance(to);
|
|
324
|
+
|
|
325
|
+
gtUint64 newFromBalance;
|
|
326
|
+
|
|
327
|
+
(newFromBalance, newToBalance, result) = MpcCore.transfer(fromBalance, toBalance, value);
|
|
328
|
+
|
|
329
|
+
_updateBalance(from, newFromBalance);
|
|
330
|
+
|
|
331
|
+
valueTransferred = MpcCore.sub(newToBalance, toBalance);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (to == address(0)) {
|
|
335
|
+
gtUint64 totalSupply_ = _safeOnboard(_totalSupply);
|
|
336
|
+
|
|
337
|
+
totalSupply_ = MpcCore.sub(totalSupply_, valueTransferred);
|
|
338
|
+
|
|
339
|
+
_totalSupply = MpcCore.offBoard(totalSupply_);
|
|
340
|
+
} else {
|
|
341
|
+
_updateBalance(to, newToBalance);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
emit Transfer(
|
|
345
|
+
from,
|
|
346
|
+
to,
|
|
347
|
+
MpcCore.offBoardToUser(valueTransferred, from),
|
|
348
|
+
MpcCore.offBoardToUser(valueTransferred, to)
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function _getBalance(address account) internal returns (gtUint64) {
|
|
355
|
+
ctUint64 ctBalance = _balances[account].ciphertext;
|
|
356
|
+
|
|
357
|
+
return _safeOnboard(ctBalance);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function _getAccountEncryptionAddress(address account) internal view returns (address) {
|
|
361
|
+
address encryptionAddress = _accountEncryptionAddress[account];
|
|
362
|
+
|
|
363
|
+
if (encryptionAddress == address(0)) {
|
|
364
|
+
encryptionAddress = account;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return encryptionAddress;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function _updateBalance(address account, gtUint64 balance) internal {
|
|
371
|
+
address encryptionAddress = _getAccountEncryptionAddress(account);
|
|
372
|
+
|
|
373
|
+
_balances[account] = MpcCore.offBoardCombined(balance, encryptionAddress);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
|
|
378
|
+
* Relies on the `_update` mechanism
|
|
379
|
+
*
|
|
380
|
+
* Emits a {Transfer} event with `from` set to the zero address.
|
|
381
|
+
*
|
|
382
|
+
* NOTE: This function is not virtual, {_update} should be overridden instead.
|
|
383
|
+
*/
|
|
384
|
+
function _mint(address account, gtUint64 value) internal returns (gtBool) {
|
|
385
|
+
if (account == address(0)) {
|
|
386
|
+
revert ERC20InvalidReceiver(address(0));
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return _update(address(0), account, value);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
|
|
394
|
+
* Relies on the `_update` mechanism.
|
|
395
|
+
*
|
|
396
|
+
* Emits a {Transfer} event with `to` set to the zero address.
|
|
397
|
+
*
|
|
398
|
+
* NOTE: This function is not virtual, {_update} should be overridden instead
|
|
399
|
+
*/
|
|
400
|
+
function _burn(address account, gtUint64 value) internal returns (gtBool) {
|
|
401
|
+
if (account == address(0)) {
|
|
402
|
+
revert ERC20InvalidSender(address(0));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return _update(account, address(0), value);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
|
|
410
|
+
*
|
|
411
|
+
* This internal function is equivalent to `approve`, and can be used to
|
|
412
|
+
* e.g. set automatic allowances for certain subsystems, etc.
|
|
413
|
+
*
|
|
414
|
+
* Emits an {Approval} event.
|
|
415
|
+
*
|
|
416
|
+
* Requirements:
|
|
417
|
+
*
|
|
418
|
+
* - `owner` cannot be the zero address.
|
|
419
|
+
* - `spender` cannot be the zero address.
|
|
420
|
+
*
|
|
421
|
+
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
|
|
422
|
+
*/
|
|
423
|
+
function _approve(address owner, address spender, gtUint64 value) internal {
|
|
424
|
+
if (owner == address(0)) {
|
|
425
|
+
revert ERC20InvalidApprover(address(0));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if (spender == address(0)) {
|
|
429
|
+
revert ERC20InvalidSpender(address(0));
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
ctUint64 ciphertext = MpcCore.offBoard(value);
|
|
433
|
+
|
|
434
|
+
address encryptionAddress = _getAccountEncryptionAddress(owner);
|
|
435
|
+
|
|
436
|
+
ctUint64 ownerCiphertext = MpcCore.offBoardToUser(value, encryptionAddress);
|
|
437
|
+
|
|
438
|
+
encryptionAddress = _getAccountEncryptionAddress(spender);
|
|
439
|
+
|
|
440
|
+
ctUint64 spenderCiphertext = MpcCore.offBoardToUser(value, encryptionAddress);
|
|
441
|
+
|
|
442
|
+
_allowances[owner][spender] = Allowance(ciphertext, ownerCiphertext, spenderCiphertext);
|
|
443
|
+
|
|
444
|
+
emit Approval(owner, spender, ownerCiphertext, spenderCiphertext);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
|
|
449
|
+
*
|
|
450
|
+
* Does not decrease the allowance value in case of infinite allowance.
|
|
451
|
+
* Does not decrease the allowance if not enough allowance is available.
|
|
452
|
+
*
|
|
453
|
+
*/
|
|
454
|
+
function _spendAllowance(address owner, address spender, gtUint64 value) internal virtual {
|
|
455
|
+
gtUint64 currentBalance = _safeOnboard(_balances[owner].ciphertext);
|
|
456
|
+
gtUint64 currentAllowance = _safeOnboard(_allowances[owner][spender].ciphertext);
|
|
457
|
+
|
|
458
|
+
gtBool maxAllowance = MpcCore.eq(currentAllowance, MpcCore.setPublic64(MAX_UINT_64));
|
|
459
|
+
gtBool insufficientBalance = MpcCore.lt(currentBalance, value);
|
|
460
|
+
gtBool inSufficientAllowance = MpcCore.lt(currentAllowance, value);
|
|
461
|
+
|
|
462
|
+
gtUint64 newAllowance = MpcCore.mux(
|
|
463
|
+
MpcCore.or(maxAllowance, MpcCore.or(insufficientBalance, inSufficientAllowance)),
|
|
464
|
+
MpcCore.sub(currentAllowance, value),
|
|
465
|
+
currentAllowance
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
_approve(owner, spender, newAllowance);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function _safeOnboard(ctUint64 value) internal returns (gtUint64) {
|
|
472
|
+
if (ctUint64.unwrap(value) == 0) {
|
|
473
|
+
return MpcCore.setPublic64(0);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return MpcCore.onBoard(value);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# PrivateERC20
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `PrivateERC20` contract is an abstract implementation of a privacy-enhanced ERC20 token. It introduces mechanisms for handling encrypted addresses and balances, allowing for more secure and private token transfers. This contract builds on top of OpenZeppelin's `Context` and the `IPrivateERC20` interface, and it integrates with the `MpcCore` library for secure multiparty computation (MPC).
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- **Solidity Version**: `^0.8.19`
|
|
10
|
+
- **License**: MIT
|
|
11
|
+
- **Dependencies**:
|
|
12
|
+
- OpenZeppelin's `Context` contract
|
|
13
|
+
- Interface `IPrivateERC20`
|
|
14
|
+
- Utility `MpcCore` for cryptographic operations.
|
|
15
|
+
|
|
16
|
+
## Table of Contents
|
|
17
|
+
- [Constants](#constants)
|
|
18
|
+
- [MAX_UINT_64](#max_uint_64)
|
|
19
|
+
- [State Variables](#state-variables)
|
|
20
|
+
- [Account Encryption Address Mapping](#account-encryption-address-mapping)
|
|
21
|
+
- [Balance Mapping](#balance-mapping)
|
|
22
|
+
- [Allowances Mapping](#allowances-mapping)
|
|
23
|
+
- [Total Supply](#total-supply)
|
|
24
|
+
- [Token Name and Symbol](#token-name-and-symbol)
|
|
25
|
+
- [Errors](#errors)
|
|
26
|
+
- [ERC20InvalidSender](#erc20invalidsender)
|
|
27
|
+
- [ERC20InvalidReceiver](#erc20invalidreceiver)
|
|
28
|
+
- [Functions](#functions)
|
|
29
|
+
- To be documented as additional logic is discovered.
|
|
30
|
+
|
|
31
|
+
## Constants
|
|
32
|
+
|
|
33
|
+
### MAX_UINT_64
|
|
34
|
+
|
|
35
|
+
```solidity
|
|
36
|
+
uint64 private constant MAX_UINT_64 = type(uint64).max;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The constant `MAX_UINT_64` represents the maximum value of a 64-bit unsigned integer. This is used as a cap for various operations in the contract.
|
|
40
|
+
|
|
41
|
+
## State Variables
|
|
42
|
+
|
|
43
|
+
### Account Encryption Address Mapping
|
|
44
|
+
|
|
45
|
+
```solidity
|
|
46
|
+
mapping(address account => address) private _accountEncryptionAddress;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This mapping associates each account (public address) with an encryption address. The encryption address could be used for handling cryptographically secure operations involving private balances and transactions.
|
|
50
|
+
|
|
51
|
+
### Balance Mapping
|
|
52
|
+
|
|
53
|
+
```solidity
|
|
54
|
+
mapping(address account => utUint64) private _balances;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The `_balances` mapping keeps track of each account's token balance, but it uses a 64-bit unsigned integer (`utUint64`). This might be intended for scaling or privacy-preserving reasons.
|
|
58
|
+
|
|
59
|
+
### Allowances Mapping
|
|
60
|
+
|
|
61
|
+
```solidity
|
|
62
|
+
mapping(address account => mapping(address spender => Allowance)) private _allowances;
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The `_allowances` mapping tracks the allowance that one account (`account`) has given to another account (`spender`). This is a standard ERC20 allowance mechanism with the added layer of the `Allowance` structure, which may handle encrypted or privacy-preserving amounts.
|
|
66
|
+
|
|
67
|
+
### Total Supply
|
|
68
|
+
|
|
69
|
+
```solidity
|
|
70
|
+
ctUint64 private _totalSupply;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The `_totalSupply` variable keeps track of the total number of tokens in existence. Like the `_balances` mapping, it uses a 64-bit unsigned integer (`ctUint64`).
|
|
74
|
+
|
|
75
|
+
### Token Name and Symbol
|
|
76
|
+
|
|
77
|
+
```solidity
|
|
78
|
+
string private _name;
|
|
79
|
+
string private _symbol;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
These variables store the name and symbol of the token, following the ERC20 standard.
|
|
83
|
+
|
|
84
|
+
## Errors
|
|
85
|
+
|
|
86
|
+
### ERC20InvalidSender
|
|
87
|
+
|
|
88
|
+
```solidity
|
|
89
|
+
error ERC20InvalidSender(address sender);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The `ERC20InvalidSender` error is raised when an invalid sender address attempts to perform a token transfer. It logs the `sender` address that caused the failure.
|
|
93
|
+
|
|
94
|
+
### ERC20InvalidReceiver
|
|
95
|
+
|
|
96
|
+
```solidity
|
|
97
|
+
error ERC20InvalidReceiver(address receiver);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The `ERC20InvalidReceiver` error is raised when a transfer fails due to an invalid receiver address. It logs the `receiver` address that caused the failure.
|
|
101
|
+
|
|
102
|
+
## Functions
|
|
103
|
+
|
|
104
|
+
Functions in the contract are abstract or unimplemented in this fragment. These likely involve ERC20-style operations, such as `transfer`, `approve`, and `transferFrom`, but with privacy-preserving adjustments, including the handling of encrypted addresses and balances.
|