-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencryptedERC20.sol
147 lines (123 loc) · 4.65 KB
/
encryptedERC20.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity >=0.8.9 <0.9.0;
import "fhevm/abstracts/EIP712WithModifier.sol";
import "fhevm/lib/TFHE.sol";
contract EncryptedERC20 is EIP712WithModifier {
euint32 private totalSupply;
string public constant name = "USDC";
uint8 public constant decimals = 18;
// used for output authorization
bytes32 private DOMAIN_SEPARATOR;
// A mapping from address to an encrypted balance.
mapping(address => euint32) internal balances;
// A mapping of the form mapping(owner => mapping(spender => allowance)).
mapping(address => mapping(address => euint32)) internal allowances;
// The owner of the contract.
address internal contractOwner;
constructor() EIP712WithModifier("Authorization token", "1") {
contractOwner = msg.sender;
}
// Sets the balance of the owner to the given encrypted balance.
function mint(bytes calldata encryptedAmount) public {
euint32 amount = TFHE.asEuint32(encryptedAmount);
balances[msg.sender] = TFHE.add(balances[msg.sender], amount);
totalSupply = TFHE.add(totalSupply, amount);
}
// Transfers an encrypted amount from the message sender address to the `to` address.
function transfer(address to, bytes calldata encryptedAmount) public {
transfer(to, TFHE.asEuint32(encryptedAmount));
}
// Transfers an amount from the message sender address to the `to` address.
function transfer(address to, euint32 amount) public {
_transfer(msg.sender, to, amount);
}
function getTotalSupply(
bytes32 publicKey,
bytes calldata signature
)
public
view
onlyContractOwner
onlySignedPublicKey(publicKey, signature)
returns (bytes memory)
{
return TFHE.reencrypt(totalSupply, publicKey);
}
// Returns the balance of the caller under their public FHE key.
// The FHE public key is automatically determined based on the origin of the call.
function balanceOf(
bytes32 publicKey,
bytes calldata signature
)
public
view
onlySignedPublicKey(publicKey, signature)
returns (bytes memory)
{
return TFHE.reencrypt(balances[msg.sender], publicKey);
}
// Sets the `encryptedAmount` as the allowance of `spender` over the caller's tokens.
function approve(address spender, bytes calldata encryptedAmount) public {
address owner = msg.sender;
_approve(owner, spender, TFHE.asEuint32(encryptedAmount));
}
// Returns the remaining number of tokens that `spender` is allowed to spend
// on behalf of the caller. The returned ciphertext is under the caller public FHE key.
function allowance(
address spender,
bytes32 publicKey,
bytes calldata signature
)
public
view
onlySignedPublicKey(publicKey, signature)
returns (bytes memory)
{
address owner = msg.sender;
return TFHE.reencrypt(_allowance(owner, spender), publicKey);
}
// Transfers `encryptedAmount` tokens using the caller's allowance.
function transferFrom(
address from,
address to,
bytes calldata encryptedAmount
) public {
transferFrom(from, to, TFHE.asEuint32(encryptedAmount));
}
// Transfers `amount` tokens using the caller's allowance.
function transferFrom(address from, address to, euint32 amount) public {
address spender = msg.sender;
_updateAllowance(from, spender, amount);
_transfer(from, to, amount);
}
function _approve(address owner, address spender, euint32 amount) internal {
allowances[owner][spender] = amount;
}
function _allowance(
address owner,
address spender
) internal view returns (euint32) {
return allowances[owner][spender];
}
function _updateAllowance(
address owner,
address spender,
euint32 amount
) internal {
euint32 currentAllowance = _allowance(owner, spender);
TFHE.req(TFHE.le(amount, currentAllowance));
_approve(owner, spender, TFHE.sub(currentAllowance, amount));
}
// Transfers an encrypted amount.
function _transfer(address from, address to, euint32 amount) internal {
// Make sure the sender has enough tokens.
TFHE.req(TFHE.le(amount, balances[from]));
// Add to the balance of `to` and subract from the balance of `from`.
balances[to] = TFHE.add(balances[to], amount);
balances[from] = TFHE.sub(balances[from], amount);
}
modifier onlyContractOwner() {
require(msg.sender == contractOwner);
_;
}
}