-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f1e2b71
commit b78d0cd
Showing
2 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity 0.8.6; | ||
|
||
import "@pooltogether/owner-manager-contracts/contracts/Manageable.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
|
||
/** | ||
* @title PoolTogether Vault | ||
* @author PoolTogether Inc Team | ||
*/ | ||
contract Vault is Manageable { | ||
using SafeERC20 for IERC20; | ||
|
||
mapping(address => bool) public approved; | ||
|
||
/** | ||
* @notice Constructs Vault | ||
* @param _owner Owner address | ||
*/ | ||
constructor(address _owner) Ownable(_owner) {} | ||
|
||
function setApproved(address _account, bool _approved) external onlyOwner { | ||
approved[_account] = _approved; | ||
} | ||
|
||
/** | ||
* @notice Decrease allowance of ERC20 tokens held by this contract. | ||
* @dev Only callable by the owner or asset manager. | ||
* @dev Current allowance should be computed off-chain to avoid any underflow. | ||
* @param token Address of the ERC20 token to decrease allowance for | ||
* @param spender Address of the spender of the tokens | ||
* @param amount Amount of tokens to decrease allowance by | ||
*/ | ||
function decreaseERC20Allowance( | ||
IERC20 token, | ||
address spender, | ||
uint256 amount | ||
) external onlyManagerOrOwner { | ||
token.safeDecreaseAllowance(spender, amount); | ||
} | ||
|
||
/** | ||
* @notice Increase allowance of ERC20 tokens held by this contract. | ||
* @dev Only callable by the owner or asset manager. | ||
* @dev Current allowance should be computed off-chain to avoid any overflow. | ||
* @param token Address of the ERC20 token to increase allowance for | ||
* @param spender Address of the spender of the tokens | ||
* @param amount Amount of tokens to increase allowance by | ||
*/ | ||
function increaseERC20Allowance( | ||
IERC20 token, | ||
address spender, | ||
uint256 amount | ||
) external onlyManagerOrOwner { | ||
require(approved[spender], "Spender must be approved"); | ||
token.safeIncreaseAllowance(spender, amount); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; | ||
import { expect } from 'chai'; | ||
import { deployMockContract } from 'ethereum-waffle'; | ||
import { Contract, Signer } from 'ethers'; | ||
import { ethers, artifacts } from 'hardhat'; | ||
|
||
const newDebug = require('debug'); | ||
|
||
const debug = newDebug('pt:Vault.test.ts'); | ||
|
||
const { getSigners } = ethers; | ||
|
||
describe('Vault', () => { | ||
let vault: Contract; | ||
let token: Contract; | ||
|
||
let wallet1: SignerWithAddress; | ||
let wallet2: SignerWithAddress; | ||
let wallet3: SignerWithAddress; | ||
let wallet4: SignerWithAddress; | ||
|
||
beforeEach(async () => { | ||
[wallet1, wallet2, wallet3, wallet4] = await getSigners(); | ||
|
||
const IERC20Artifact = await artifacts.readArtifact('IERC20'); | ||
token = await deployMockContract(wallet1 as Signer, IERC20Artifact.abi); | ||
|
||
const VaultFactory = await ethers.getContractFactory('Vault', wallet1); | ||
vault = await VaultFactory.deploy(wallet1.address); | ||
}); | ||
|
||
describe('constructor', () => { | ||
it('should set the owner', async () => { | ||
expect(await vault.owner()).to.equal(wallet1.address) | ||
}) | ||
}) | ||
|
||
describe('setApproval()', () => { | ||
it('should allow the owner to approve accounts', async () => { | ||
await vault.setApproved(wallet2.address, true) | ||
expect(await vault.approved(wallet2.address)).to.equal(true) | ||
}) | ||
}) | ||
|
||
describe('increaseERC20Allowance()', () => { | ||
it('should allow owners to increase approval amount', async () => { | ||
await vault.setApproved(wallet2.address, true) | ||
await token.mock.allowance.withArgs(vault.address, wallet2.address).returns('0') | ||
await token.mock.approve.withArgs(wallet2.address, '1111').returns(true) | ||
await vault.increaseERC20Allowance(token.address, wallet2.address, '1111') | ||
}) | ||
|
||
it('should allow managers to increase approval amount', async () => { | ||
await vault.setManager(wallet3.address) | ||
await vault.setApproved(wallet2.address, true) | ||
await token.mock.allowance.withArgs(vault.address, wallet2.address).returns('0') | ||
await token.mock.approve.withArgs(wallet2.address, '1111').returns(true) | ||
await vault.connect(wallet3).increaseERC20Allowance(token.address, wallet2.address, '1111') | ||
}) | ||
}) | ||
|
||
describe('decreaseERC20Allowance()', () => { | ||
it('should allow manager to decrease approval amount', async () => { | ||
await token.mock.allowance.withArgs(vault.address, wallet2.address).returns('1111') | ||
await token.mock.approve.withArgs(wallet2.address, '111').returns(true) | ||
await vault.decreaseERC20Allowance(token.address, wallet2.address, '1000') | ||
}) | ||
|
||
it('should allow manager to decrease approval amount', async () => { | ||
await vault.setManager(wallet3.address) | ||
await token.mock.allowance.withArgs(vault.address, wallet2.address).returns('1111') | ||
await token.mock.approve.withArgs(wallet2.address, '0').returns(true) | ||
await vault.connect(wallet3).decreaseERC20Allowance(token.address, wallet2.address, '1111') | ||
}) | ||
}) | ||
}); |