Skip to content

Commit

Permalink
feat: VaultManager implementation with interface IERC1155Receiver (#210)
Browse files Browse the repository at this point in the history
* first batch of test done

* update final hash of vaultManager implementation

* changing whitelist

* vaultManager for IB01

* fix: comments for liquidations

* add USDC collateral

* feat: add ERC1155 support

* fix: failed tests corrected

* fix-rebase

* avoid skipped line

---------

Co-authored-by: gs8nrv <[email protected]>
  • Loading branch information
sogipec and GuillaumeNervoXS authored Jan 19, 2024
1 parent 407a0e9 commit 53c0990
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 6 deletions.
2 changes: 1 addition & 1 deletion contracts/vaultManager/VaultManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ contract VaultManager is VaultManagerPermit, IVaultManagerFunctions {
/// @param target Address to toggle
/// @dev If the `target` address is the zero address then this function toggles whitelisting
/// for all addresses
function toggleWhitelist(address target) external virtual onlyGovernor {
function toggleWhitelist(address target) external virtual onlyGovernorOrGuardian {
if (target != address(0)) {
isWhitelisted[target] = 1 - isWhitelisted[target];
} else {
Expand Down
44 changes: 44 additions & 0 deletions contracts/vaultManager/VaultManagerERC1155Receiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.12;

import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155ReceiverUpgradeable.sol";

import "./VaultManager.sol";

/// @title VaultManagerERC1155Receiver
/// @author Angle Labs, Inc.
/// @notice VaultManager contract that can receive ERC1155 tokens
contract VaultManagerERC1155Receiver is IERC1155ReceiverUpgradeable, VaultManager {
/// @inheritdoc IERC1155ReceiverUpgradeable
/// @dev The returned value should be:
/// `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) = 0xf23a6e61`
function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) {
return IERC1155ReceiverUpgradeable.onERC1155Received.selector;
}

/// @inheritdoc IERC1155ReceiverUpgradeable
/// @dev The returned value should be:
/// `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)")) = 0xbc197c81`
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external pure returns (bytes4) {
return IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector;
}

/// @inheritdoc IERC165Upgradeable
function supportsInterface(
bytes4 interfaceId
) external pure override(VaultManagerERC721, IERC165Upgradeable) returns (bool) {
return
interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||
interfaceId == type(IERC721Upgradeable).interfaceId ||
interfaceId == type(IVaultManager).interfaceId ||
interfaceId == type(IERC165Upgradeable).interfaceId ||
interfaceId == type(IERC1155ReceiverUpgradeable).interfaceId;
}
}
2 changes: 1 addition & 1 deletion contracts/vaultManager/VaultManagerERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ abstract contract VaultManagerERC721 is IERC721MetadataUpgradeable, VaultManager
// ================================ ERC165 LOGIC ===============================

/// @inheritdoc IERC165Upgradeable
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
function supportsInterface(bytes4 interfaceId) external pure virtual returns (bool) {
return
interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||
interfaceId == type(IERC721Upgradeable).interfaceId ||
Expand Down
9 changes: 9 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ const config: HardhatUserConfig = {
},
},
},
'contracts/vaultManager/VaultManagerERC1155Receiver.sol': {
version: '0.8.12',
settings: {
optimizer: {
enabled: true,
runs: 1,
},
},
},
'contracts/deprecated/OldVaultManager.sol': {
version: '0.8.12',
settings: {
Expand Down
124 changes: 124 additions & 0 deletions test/hardhat/vaultManager/vaultManagerERC1155Receiver.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { parseAmount } from '@angleprotocol/sdk';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { Signer } from 'ethers';
import { parseEther } from 'ethers/lib/utils';
import hre, { contract, ethers } from 'hardhat';

import {
AgToken,
AgToken__factory,
AngleHelpers,
AngleHelpers__factory,
MockOracle,
MockOracle__factory,
MockStableMaster,
MockStableMaster__factory,
MockToken,
MockToken__factory,
MockTreasury,
MockTreasury__factory,
VaultManagerERC1155Receiver,
VaultManagerERC1155Receiver__factory,
} from '../../../typechain';
import { expect } from '../utils/chai-setup';
import { deployUpgradeable, ZERO_ADDRESS } from '../utils/helpers';

contract('VaultManagerERC1155Receiver', () => {
let deployer: SignerWithAddress;
let governor: SignerWithAddress;
let guardian: SignerWithAddress;

let treasury: MockTreasury;
let collateral: MockToken;
let oracle: MockOracle;
let stableMaster: MockStableMaster;
let agToken: AgToken;
let vaultManager: VaultManagerERC1155Receiver;
let helpers: AngleHelpers;

const impersonatedSigners: { [key: string]: Signer } = {};

const collatBase = 10;
const params = {
debtCeiling: parseEther('100'),
collateralFactor: 0.5e9,
targetHealthFactor: 1.1e9,
borrowFee: 0.1e9,
interestRate: 100,
liquidationSurcharge: 0.9e9,
maxLiquidationDiscount: 0.1e9,
liquidationBooster: 0.1e9,
whitelistingActivated: false,
baseBoost: 1e9,
};

before(async () => {
({ deployer, governor, guardian } = await ethers.getNamedSigners());
const impersonatedAddresses = [{ address: '0xdC4e6DFe07EFCa50a197DF15D9200883eF4Eb1c8', name: 'governor' }];

for (const ob of impersonatedAddresses) {
await hre.network.provider.request({
method: 'hardhat_impersonateAccount',
params: [ob.address],
});

await hre.network.provider.send('hardhat_setBalance', [ob.address, '0x10000000000000000000000000000']);

impersonatedSigners[ob.name] = await ethers.getSigner(ob.address);
}
});

beforeEach(async () => {
stableMaster = await new MockStableMaster__factory(deployer).deploy();
agToken = (await deployUpgradeable(new AgToken__factory(deployer))) as AgToken;
await agToken.connect(deployer).initialize('agEUR', 'agEUR', stableMaster.address);
collateral = await new MockToken__factory(deployer).deploy('USDC', 'USDC', collatBase);
vaultManager = (await deployUpgradeable(
new VaultManagerERC1155Receiver__factory(deployer),
)) as VaultManagerERC1155Receiver;
helpers = (await deployUpgradeable(new AngleHelpers__factory(deployer))) as AngleHelpers;

treasury = await new MockTreasury__factory(deployer).deploy(
agToken.address,
governor.address,
guardian.address,
vaultManager.address,
ZERO_ADDRESS,
ZERO_ADDRESS,
);
await agToken.connect(impersonatedSigners.governor).setUpTreasury(treasury.address);
await treasury.addMinter(agToken.address, vaultManager.address);

oracle = await new MockOracle__factory(deployer).deploy(2 * 10 ** collatBase, treasury.address);
await vaultManager.initialize(treasury.address, collateral.address, oracle.address, params, 'USDC/agEUR');
});

describe('ERC1155Receiver Logic', () => {
it('success - onERC1155Received', async () => {
expect(
await vaultManager.onERC1155Received(
guardian.address,
guardian.address,
parseEther('1'),
parseEther('2'),
'0x',
),
).to.be.equal('0xf23a6e61');
});
it('success - onERC1155BatchReceived', async () => {
expect(
await vaultManager.onERC1155BatchReceived(
guardian.address,
guardian.address,
[parseAmount.gwei('1')],
[parseEther('10')],
'0x',
),
).to.be.equal('0xbc197c81');
});
it('success - supportsInterface', async () => {
// Equal to: `type(IERC1155ReceiverUpgradeable).interfaceId`
expect(await vaultManager.supportsInterface('0x4e2312e0')).to.be.equal(true);
});
});
});
1 change: 0 additions & 1 deletion test/hardhat/vaultManager/vaultManagerERC721.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ contract('VaultManagerLiquidationBoost - ERC721', () => {
expect(await vaultManager.paused()).to.be.false;

await expect(vaultManager.connect(deployer).toggleWhitelist(ZERO_ADDRESS)).to.be.reverted;
await expect(vaultManager.connect(guardian).toggleWhitelist(ZERO_ADDRESS)).to.be.reverted;
await vaultManager.connect(governor).toggleWhitelist(ZERO_ADDRESS);
expect(await vaultManager.whitelistingActivated()).to.be.true;
});
Expand Down
12 changes: 9 additions & 3 deletions test/hardhat/vaultManager/vaultManagerSetters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,16 @@ contract('VaultManagerLiquidationBoost - Setters', () => {

describe('toggleWhitelist', () => {
it('reverts - access control', async () => {
await expect(vaultManager.connect(alice).toggleWhitelist(alice.address)).to.be.revertedWith('NotGovernor');
await expect(vaultManager.connect(alice).toggleWhitelist(alice.address)).to.be.revertedWith(
'NotGovernorOrGuardian',
);
});
it('reverts - guardian', async () => {
await expect(vaultManager.connect(guardian).toggleWhitelist(alice.address)).to.be.revertedWith('NotGovernor');
it('success - guardian', async () => {
await vaultManager.connect(guardian).toggleWhitelist(alice.address);
expect(await vaultManager.isWhitelisted(alice.address)).to.be.equal(1);

await vaultManager.connect(guardian).toggleWhitelist(alice.address);
expect(await vaultManager.isWhitelisted(alice.address)).to.be.equal(0);
});
it('success - governor', async () => {
await vaultManager.connect(governor).toggleWhitelist(alice.address);
Expand Down

0 comments on commit 53c0990

Please sign in to comment.