Skip to content

Commit

Permalink
Merge pull request #8 from sirnicolaz/miotto/lila-6086-update-faucet-…
Browse files Browse the repository at this point in the history
…to-support-any-kind-of-pool-token

[LILA-6086] Support multiple pools
  • Loading branch information
0xmichalis authored Feb 19, 2024
2 parents 8d605e0 + 046d1f0 commit 51985f1
Show file tree
Hide file tree
Showing 6 changed files with 547 additions and 72 deletions.
126 changes: 59 additions & 67 deletions contracts/Faucet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,113 +9,105 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract Faucet is Ownable {
using SafeERC20 for IERC20;

uint256 public constant TIMEOUT_LIMIT = 30;
uint256 public constant MAX_WITHDRAWAL_AMOUNT = 5 ether;
address public contractRegistry;
address public bctAddress;
address public nctAddress;
mapping(address => uint256) private lastWithdrawalTimes;
mapping(address => bool) public isPoolEligible;
mapping(address => uint256) private _lastWithdrawalTimes;
event Deposited(address erc20Addr, uint256 amount);
event Withdrawn(address account, address erc20Addr, uint256 amount);

constructor(
address _contractRegistry,
address _bctAddress,
address _nctAddress
) {
contractRegistry = _contractRegistry;
bctAddress = _bctAddress;
nctAddress = _nctAddress;
constructor(address contractRegistry_, address[] memory poolAddresses) {
contractRegistry = contractRegistry_;

uint256 poolAddressesCount = poolAddresses.length;
for (uint256 i = 0; i < poolAddressesCount; i++) {
setPoolEligible(poolAddresses[i], true);
}
}

/// @notice change the TCO2 contracts registry
/// @param _address the new contract registry address
/// @param contractRegistry_ the new contract registry address
function setToucanContractRegistry(
address _address
address contractRegistry_
) public virtual onlyOwner {
contractRegistry = contractRegistry_;
}

/// @notice allows the owner to set the eligibility of a pool
/// @param poolAddress the address of the pool
/// @param isPoolEligible_ eligibility flag
function setPoolEligible(
address poolAddress,
bool isPoolEligible_
) public virtual onlyOwner {
contractRegistry = _address;
isPoolEligible[poolAddress] = isPoolEligible_;
}

/// @notice A function to get the Faucet's balances of multiple tokens at once
/// @param _erc20Addresses An array of ERC20 contract addresses
/// @param erc20Addresses An array of ERC20 contract addresses
/// @return An array of balances
function getTokenBalances(
address[] memory _erc20Addresses
address[] memory erc20Addresses
) public view returns (uint256[] memory) {
uint256[] memory balances = new uint256[](_erc20Addresses.length);
for (uint256 i = 0; i < _erc20Addresses.length; i++) {
balances[i] = IERC20(_erc20Addresses[i]).balanceOf(address(this));
uint256[] memory balances = new uint256[](erc20Addresses.length);
for (uint256 i = 0; i < erc20Addresses.length; i++) {
balances[i] = IERC20(erc20Addresses[i]).balanceOf(address(this));
}
return balances;
}

/// @notice checks if token to be deposited is eligible for the Faucet
/// @param _erc20Address address to be checked
function checkTokenEligibility(
address _erc20Address
) private view returns (bool) {
bool isToucanContract = IToucanContractRegistry(contractRegistry)
.checkERC20(_erc20Address);
if (isToucanContract) return true;

if (_erc20Address == bctAddress) return true;

if (_erc20Address == nctAddress) return true;

return false;
}

/// @notice deposit tokens from caller to Faucet
/// @param _erc20Address ERC20 contract address to be deposited
/// @param _amount amount to be deposited
function deposit(address _erc20Address, uint256 _amount) public {
bool eligibility = checkTokenEligibility(_erc20Address);
require(eligibility, "Token rejected");
/// @param erc20Address ERC20 contract address to be deposited
/// @param amount amount to be deposited
function deposit(address erc20Address, uint256 amount) public {
require(_checkEligible(erc20Address), "Token rejected");

IERC20(_erc20Address).safeTransferFrom(
IERC20(erc20Address).safeTransferFrom(
msg.sender,
address(this),
_amount
amount
);

emit Deposited(_erc20Address, _amount);
emit Deposited(erc20Address, amount);
}

/// @notice checks if the Faucet is in a withdrawal timeout for the caller
/// @return true if in timeout, false if not
function checkIfWithdrawalTimeout() public returns (bool) {
uint256 timeoutLimit = 30; // amount of seconds in between withdrawals
if (lastWithdrawalTimes[msg.sender] == 0) {
lastWithdrawalTimes[msg.sender] = block.timestamp - timeoutLimit;
}
if (lastWithdrawalTimes[msg.sender] <= block.timestamp - timeoutLimit) {
return false;
}
return true;
function checkIfWithdrawalTimeout() public view returns (bool) {
return
_lastWithdrawalTimes[msg.sender] > block.timestamp - TIMEOUT_LIMIT;
}

/// @notice withdraw tokens from Faucet to caller
/// @param _erc20Address ERC20 contract address to be withdrawn
/// @param _amount amount to be withdrawn
function withdraw(address _erc20Address, uint256 _amount) public {
bool eligibility = checkTokenEligibility(_erc20Address);
require(eligibility, "Token rejected");

/// @param erc20Address ERC20 contract address to be withdrawn
/// @param amount amount to be withdrawn
function withdraw(address erc20Address, uint256 amount) public {
require(_checkEligible(erc20Address), "Token rejected");
require(!checkIfWithdrawalTimeout(), "Cannot withdraw that often");
lastWithdrawalTimes[msg.sender] = block.timestamp;
_lastWithdrawalTimes[msg.sender] = block.timestamp;

require(_amount <= 5 ether, "Cannot withdraw more than 5 tokens");
require(amount <= MAX_WITHDRAWAL_AMOUNT, "Amount too high");

IERC20(_erc20Address).safeTransfer(msg.sender, _amount);
IERC20(erc20Address).safeTransfer(msg.sender, amount);

emit Withdrawn(msg.sender, _erc20Address, _amount);
emit Withdrawn(msg.sender, erc20Address, amount);
}

/// @notice function that is only callable by owner and can withdraw as many tokens from this contract as they want
/// @param _erc20Address address of the token to be withdrawn
/// @param _amount amount of tokens to be withdrawn
/// @param erc20Address address of the token to be withdrawn
/// @param amount amount of tokens to be withdrawn
function ownerWithdraw(
address _erc20Address,
uint256 _amount
address erc20Address,
uint256 amount
) public onlyOwner {
IERC20(_erc20Address).safeTransfer(msg.sender, _amount);
IERC20(erc20Address).safeTransfer(msg.sender, amount);
}

function _checkEligible(address erc20Address) internal view returns (bool) {
return
IToucanContractRegistry(contractRegistry).checkERC20(
erc20Address
) || isPoolEligible[erc20Address];
}
}
2 changes: 1 addition & 1 deletion deploy/00_deploy_faucet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {

await deploy("Faucet", {
from: deployer,
args: [CONTRACT_REGISTRY_ADDRESS, BCT_ADDRESS, NCT_ADDRESS],
args: [CONTRACT_REGISTRY_ADDRESS, [BCT_ADDRESS, NCT_ADDRESS]],
log: true,
autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks
});
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@
"typescript": "^4.5.5"
},
"dependencies": {
"@defi-wonderland/smock": "^2.3.5",
"@nomicfoundation/hardhat-network-helpers": "^1.0.7",
"@openzeppelin/contracts": "^4.8.0",
"@openzeppelin/contracts-upgradeable": "^4.4.2",
"@types/chai-as-promised": "^7.1.8",
"chai-as-promised": "^7.1.1",
"mocha": "^10.3.0",
"solc": "^0.8.11"
}
}
7 changes: 3 additions & 4 deletions test/index.ts → test/Integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ describe("TCO2Faucet", function () {
)) as Faucet__factory;
const { CONTRACT_REGISTRY_ADDRESS, BCT_ADDRESS, NCT_ADDRESS } =
deploymentAddresses.mumbai;
const faucet = await FaucetFactory.deploy(
CONTRACT_REGISTRY_ADDRESS,
const faucet = await FaucetFactory.deploy(CONTRACT_REGISTRY_ADDRESS, [
BCT_ADDRESS,
NCT_ADDRESS
);
NCT_ADDRESS,
]);

let TCO2Contracts: Record<string, IERC20> = {};

Expand Down
Loading

0 comments on commit 51985f1

Please sign in to comment.