Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions contracts/ConfidentialERC20/ConfidentialERC20.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;
pragma solidity ^0.8.24;

import { IConfidentialERC20 } from "./Interfaces/IConfidentialERC20.sol";
import { IERC20Metadata } from "./Utils/IERC20Metadata.sol";
Expand Down Expand Up @@ -228,7 +228,7 @@ abstract contract ConfidentialERC20 is Ownable, IConfidentialERC20, IERC20Metada
}
_balances[account] = TFHE.add(_balances[account], value);
TFHE.allow(_balances[account], address(this));
TFHE.allow(_balances[account], msg.sender);
TFHE.allow(_balances[account], account);
_totalSupply += value;
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/ConfidentialERC20/ConfidentialToken.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.20;
pragma solidity ^0.8.24;

import "./ConfidentialERC20.sol";
import "fhevm/lib/TFHE.sol";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
import "fhevm/lib/TFHE.sol";

pragma solidity ^0.8.20;
pragma solidity ^0.8.24;

/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
Expand Down
2 changes: 1 addition & 1 deletion contracts/ConfidentialERC20/Utils/Context.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;
pragma solidity ^0.8.24;

/**
* @dev Provides information about the current execution context, including the
Expand Down
2 changes: 1 addition & 1 deletion contracts/ConfidentialERC20/Utils/IERC20Metadata.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;
pragma solidity ^0.8.24;

import { IConfidentialERC20 } from "../Interfaces/IConfidentialERC20.sol";

Expand Down
2 changes: 1 addition & 1 deletion contracts/ConfidentialERC20/Utils/IERC6093.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
pragma solidity ^0.8.24;
import "fhevm/lib/TFHE.sol";
/**
* @dev Standard ERC-20 Errors
Expand Down
18 changes: 16 additions & 2 deletions contracts/ConfidentialERC20Wrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,39 @@ import "fhevm/gateway/GatewayCaller.sol";
import { ConfidentialToken } from "./ConfidentialERC20/ConfidentialToken.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
interface IERC20extended is IERC20 {
function decimals() external view returns (uint8);
}

contract ConfidentialERC20Wrapper is ConfidentialToken {
using SafeERC20 for IERC20;
IERC20 public baseERC20;
mapping(address => bool) public unwrapDisabled;
uint8 private _decimals;
event Wrap(address indexed account, uint64 amount);
event Unwrap(address indexed account, uint64 amount);
event Burn(address indexed account, uint64 amount);

error UnwrapNotAllowed(address account);

constructor(address _baseERC20) ConfidentialToken("Wrapped cERC20", "wcERC20") {
uint8 baseERCdecimals = IERC20extended(_baseERC20).decimals();
require(baseERCdecimals <= 6, "Base ERC20 token must have 6 or less decimals");
baseERC20 = IERC20(_baseERC20);
_decimals = baseERCdecimals;
// set the wrapper decimals to be the same as the base token
}

function decimals() public view override returns (uint8) {
return _decimals;
}

function wrap(uint64 amount) external {
uint256 _amount = uint256(amount);
uint256 allowance = baseERC20.allowance(msg.sender, address(this));
require(allowance >= _amount, "Not enough allowance");
baseERC20.transferFrom(msg.sender, address(this), _amount);
baseERC20.safeTransferFrom(msg.sender, address(this), _amount);
_mint(msg.sender, uint64(amount));
emit Wrap(msg.sender, amount);
}
Expand All @@ -47,7 +61,7 @@ contract ConfidentialERC20Wrapper is ConfidentialToken {
}

// Call base ERC20 transfer and emit Unwrap event
baseERC20.transfer(account, amount);
baseERC20.safeTransfer(account, amount);
emit Unwrap(account, amount);

// Continue with the burn logic
Expand Down
3 changes: 3 additions & 0 deletions contracts/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ contract MyToken is ERC20 {
constructor() ERC20("MyToken", "MTK") {
_mint(msg.sender, 1000);
}
function decimals() public pure override returns (uint8) {
return 6;
}
}
25 changes: 25 additions & 0 deletions test/ConfidentialERC20Tests/ConfidentialERC20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,32 @@ describe("Confidential ERC20 tests", function () {
const totalSupply = await this.erc20.totalSupply();
expect(totalSupply).to.equal(1000);
});
it("should mint to bob", async function () {
const transaction = await this.erc20.mint(this.signers.bob, 1000);
await transaction.wait();

//Reencrypt Bob's balance
const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob);
const { publicKey: publicKeyBob, privateKey: privateKeyBob } = this.instances.bob.generateKeypair();
const eip712 = this.instances.bob.createEIP712(publicKeyBob, this.contractAddress);
const signatureBob = await this.signers.bob.signTypedData(
eip712.domain,
{ Reencrypt: eip712.types.Reencrypt },
eip712.message,
);
const balanceBob = await this.instances.bob.reencrypt(
balanceHandleBob,
privateKeyBob,
publicKeyBob,
signatureBob.replace("0x", ""),
this.contractAddress,
this.signers.bob.address,
);
expect(balanceBob).to.equal(1000);

const totalSupply = await this.erc20.totalSupply();
expect(totalSupply).to.equal(1000);
});
it("should transfer tokens between two users", async function () {
const transaction = await this.erc20.mint(this.signers.alice, 10000);
const t1 = await transaction.wait();
Expand Down