Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[EFIP-5] {Permit Whitelist, Transfer Blacklist}" #206

Merged
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
49 changes: 4 additions & 45 deletions src/EETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,12 @@ import "./interfaces/ILiquidityPool.sol";

contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20PermitUpgradeable, IeETH {
using CountersUpgradeable for CountersUpgradeable.Counter;
//--------------------------------------------------------------------------------------
//--------------------------------- STATE-VARIABLES ----------------------------------
//--------------------------------------------------------------------------------------

ILiquidityPool public liquidityPool;

uint256 public totalShares;
mapping (address => uint256) public shares;
mapping (address => mapping (address => uint256)) public allowances;
mapping (address => CountersUpgradeable.Counter) private _nonces;
mapping (address => bool) public whitelistedSpender;
mapping (address => bool) public blacklistedRecipient;

bytes32 private constant _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

Expand All @@ -40,16 +34,9 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;

//--------------------------------------------------------------------------------------
//------------------------------------ EVENTS ----------------------------------------
//--------------------------------------------------------------------------------------

event TransferShares( address indexed from, address indexed to, uint256 sharesValue);

//--------------------------------------------------------------------------------------
//---------------------------- STATE-CHANGING FUNCTIONS ------------------------------
//--------------------------------------------------------------------------------------

// TODO: Figure our what `name` and `version` are for
constructor() {
bytes32 hashedName = keccak256("EETH");
bytes32 hashedVersion = keccak256("1");
Expand Down Expand Up @@ -140,7 +127,6 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P
bytes32 r,
bytes32 s
) public virtual override(IeETH, IERC20PermitUpgradeable) {
require(whitelistedSpender[spender], "eETH: spender not whitelisted");
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
Expand All @@ -153,13 +139,8 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P
_approve(owner, spender, value);
}

//--------------------------------------------------------------------------------------
//------------------------------- INTERNAL FUNCTIONS ---------------------------------
//--------------------------------------------------------------------------------------

// [INTERNAL FUNCTIONS]
function _transfer(address _sender, address _recipient, uint256 _amount) internal {
require(!blacklistedRecipient[_sender] && !blacklistedRecipient[_recipient], "eETH: blacklisted address");

uint256 _sharesToTransfer = liquidityPool.sharesForAmount(_amount);
_transferShares(_sender, _recipient, _sharesToTransfer);
emit Transfer(_sender, _recipient, _amount);
Expand Down Expand Up @@ -194,26 +175,7 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P
nonce.increment();
}

//--------------------------------------------------------------------------------------
//------------------------------------ SETTERS ---------------------------------------
//--------------------------------------------------------------------------------------

function setWhitelistedSpender(address[] calldata _spenders, bool _isWhitelisted) external onlyOwner {
for (uint i = 0; i < _spenders.length; i++) {
whitelistedSpender[_spenders[i]] = _isWhitelisted;
}
}

function setBlacklistedRecipient(address[] calldata _recipients, bool _isBlacklisted) external onlyOwner {
for (uint i = 0; i < _recipients.length; i++) {
blacklistedRecipient[_recipients[i]] = _isBlacklisted;
}
}

//--------------------------------------------------------------------------------------
//------------------------------------ GETTERS ---------------------------------------
//--------------------------------------------------------------------------------------

// [GETTERS]
function name() public pure returns (string memory) { return "ether.fi ETH"; }
function symbol() public pure returns (string memory) { return "eETH"; }
function decimals() public pure returns (uint8) { return 18; }
Expand Down Expand Up @@ -258,10 +220,7 @@ contract EETH is IERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IERC20P
return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);
}

//--------------------------------------------------------------------------------------
//------------------------------------ MODIFIER --------------------------------------
//--------------------------------------------------------------------------------------

// [MODIFIERS]
modifier onlyPoolContract() {
require(msg.sender == address(liquidityPool), "Only pool contract function");
_;
Expand Down
61 changes: 1 addition & 60 deletions src/WeETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20Pe
IeETH public eETH;
ILiquidityPool public liquidityPool;

mapping (address => bool) public whitelistedSpender;
mapping (address => bool) public blacklistedRecipient;

//--------------------------------------------------------------------------------------
//---------------------------- STATE-CHANGING FUNCTIONS ------------------------------
//--------------------------------------------------------------------------------------
Expand All @@ -29,9 +26,6 @@ contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20Pe
_disableInitializers();
}

/// @notice Initializes the contract with the specified liquidity pool and eETH addresses
/// @param _liquidityPool The address of the liquidity pool
/// @param _eETH The address of the eETH contract
function initialize(address _liquidityPool, address _eETH) external initializer {
require(_liquidityPool != address(0), "No zero addresses");
require(_eETH != address(0), "No zero addresses");
Expand Down Expand Up @@ -82,64 +76,14 @@ contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20Pe
return eETHAmount;
}

/// @notice Requires the spender to be whitelisted before calling {ERC20PermitUpgradeable-permit}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public override {
require(whitelistedSpender[spender], "weETH: spender not whitelisted");

super.permit(owner, spender, value, deadline, v, r, s);
}

//--------------------------------------------------------------------------------------
//------------------------------- INTERNAL FUNCTIONS ---------------------------------
//--------------------------------------------------------------------------------------

/// @dev Authorizes the upgrade of the contract to a new implementation by the owner
/// @param newImplementation The address of the new contract implementation
function _authorizeUpgrade(
address newImplementation
) internal override onlyOwner {}


/// @notice Require the recipient to not be blacklisted before calling {ERC20Upgradeable-_transfer}
function _transfer(
address from,
address to,
uint256 amount
) internal override {
require(!blacklistedRecipient[from] && !blacklistedRecipient[to], "weETH: blacklisted address");
super._transfer(from, to, amount);
}

//--------------------------------------------------------------------------------------
//------------------------------------ SETTERS ---------------------------------------
//--------------------------------------------------------------------------------------

/// @notice Sets the whitelisted status for a list of addresses
/// @param _spenders An array of spender addresses
/// @param _isWhitelisted Boolean value to set the whitelisted status
function setWhitelistedSpender(address[] calldata _spenders, bool _isWhitelisted) external onlyOwner {
for (uint i = 0; i < _spenders.length; i++) {
whitelistedSpender[_spenders[i]] = _isWhitelisted;
}
}

/// @notice Sets the blacklisted status for a list of addresses
/// @param _recipients An array of recipient addresses
/// @param _isBlacklisted Boolean value to set the blacklisted status
function setBlacklistedRecipient(address[] calldata _recipients, bool _isBlacklisted) external onlyOwner {
for (uint i = 0; i < _recipients.length; i++) {
blacklistedRecipient[_recipients[i]] = _isBlacklisted;
}
}

//--------------------------------------------------------------------------------------
//------------------------------------ GETTERS ---------------------------------------
//--------------------------------------------------------------------------------------
Expand All @@ -158,14 +102,11 @@ contract WeETH is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC20Pe
return liquidityPool.amountForShare(_weETHAmount);
}

/// @notice Fetches the exchange rate of eETH for 1 weETH
/// @return The amount of eETH for 1 weETH
// Amount of eETH for 1 weETH
function getRate() external view returns (uint256) {
return getEETHByWeETH(1 ether);
}

/// @notice Fetches the address of the current contract implementation
/// @return The address of the current implementation
function getImplementation() external view returns (address) {
return _getImplementation();
}
Expand Down
55 changes: 0 additions & 55 deletions test/EETH.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -300,59 +300,4 @@ contract EETHTest is TestSetup {
assertEq(eETHInstance.allowance(alice, bob), 0.5 ether);
}

function test_PermitWhitelistEETH() public {
startHoax(alice);
liquidityPoolInstance.deposit{value: 1 ether}();
vm.stopPrank();

// alice approves bob to spend 1 ether of eETH
bytes32 permitHash = keccak256(
abi.encodePacked(
"\x19\x01",
eETHInstance.DOMAIN_SEPARATOR(),
keccak256(abi.encode(
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
alice,
address(bob),
1 ether,
eETHInstance.nonces(alice),
block.timestamp
))
)
);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(2, permitHash);

vm.expectRevert("eETH: spender not whitelisted");
eETHInstance.permit(alice, bob, 1 ether, block.timestamp, v, r, s);

address[] memory whitelist = new address[](1);
whitelist[0] = bob;
vm.prank(owner);
eETHInstance.setWhitelistedSpender(whitelist, true);

eETHInstance.permit(alice, bob, 1 ether, block.timestamp, v, r, s);
vm.prank(bob);
eETHInstance.transferFrom(alice, bob, 1 ether);
}

function test_TransferBlacklistEETH() public {
startHoax(alice);
liquidityPoolInstance.deposit{value: 2 ether}();

eETHInstance.transfer(bob, 1 ether);
vm.stopPrank();

vm.prank(owner);
address[] memory blacklist = new address[](1);
blacklist[0] = bob;
eETHInstance.setBlacklistedRecipient(blacklist, true);

vm.prank(alice);
vm.expectRevert("eETH: blacklisted address");
eETHInstance.transfer(bob, 1 ether);

vm.prank(bob);
vm.expectRevert("eETH: blacklisted address");
eETHInstance.transfer(alice, 1 ether);
}
}
7 changes: 0 additions & 7 deletions test/TestSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -733,13 +733,6 @@ contract TestSetup is Test {
_initializeEtherFiAdmin();

admin = alice;

// weETH and Liquidity Pool must be on eETH to function as expected
vm.prank(owner);
address[] memory whitelist = new address[](2);
whitelist[0] = address(weEthInstance);
whitelist[1] = address(liquidityPoolInstance);
eETHInstance.setWhitelistedSpender(whitelist, true);
}

function _initOracleReportsforTesting() internal {
Expand Down
56 changes: 0 additions & 56 deletions test/WeETH.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ contract WeETHTest is TestSetup {
//Approve the wrapped eth contract to spend 100 eEth
eETHInstance.approve(address(weEthInstance), 100 ether);
weEthInstance.wrap(5 ether);
vm.stopPrank();

assertEq(weEthInstance.balanceOf(alice), 5 ether);
assertEq(eETHInstance.balanceOf(alice), 5 ether);
Expand Down Expand Up @@ -290,59 +289,4 @@ contract WeETHTest is TestSetup {
weEthInstance.unwrap(1 ether);
assertEq(eETHInstance.balanceOf(bob), 1.333333333333333332 ether);
}

function test_PermitWhitelistWeETH() public {
// allocationg weETH to alice
test_WrapWorksCorrectly();

// alice approves bob to spend 1 ether of weETH
bytes32 permitHash = keccak256(
abi.encodePacked(
"\x19\x01",
weEthInstance.DOMAIN_SEPARATOR(),
keccak256(abi.encode(
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
alice,
address(bob),
1 ether,
weEthInstance.nonces(alice),
block.timestamp
))
)
);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(2, permitHash);

vm.expectRevert("weETH: spender not whitelisted");
weEthInstance.permit(alice, bob, 1 ether, block.timestamp, v, r, s);

address[] memory whitelist = new address[](1);
whitelist[0] = bob;
vm.prank(owner);
weEthInstance.setWhitelistedSpender(whitelist, true);

weEthInstance.permit(alice, bob, 1 ether, block.timestamp, v, r, s);
vm.prank(bob);
weEthInstance.transferFrom(alice, bob, 1 ether);
}

function test_TransferBlacklistWeETH() public {
// allocationg weETH to alice
test_WrapWorksCorrectly();

vm.prank(alice);
weEthInstance.transfer(bob, 1 ether);

vm.prank(owner);
address[] memory blacklist = new address[](1);
blacklist[0] = bob;
weEthInstance.setBlacklistedRecipient(blacklist, true);

vm.prank(alice);
vm.expectRevert("weETH: blacklisted address");
weEthInstance.transfer(bob, 1 ether);

vm.prank(bob);
vm.expectRevert("weETH: blacklisted address");
weEthInstance.transfer(alice, 1 ether);
}
}
Loading