Skip to content

Commit

Permalink
Created FeeBurner
Browse files Browse the repository at this point in the history
  • Loading branch information
asselstine committed Feb 20, 2024
1 parent 14f4ff1 commit bdaa90b
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 65 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -12,3 +12,6 @@ out/
.envrc
lcov.info
node_modules

.env
.history
3 changes: 2 additions & 1 deletion remappings.txt
@@ -1,3 +1,4 @@
ds-test/=lib/forge-std/lib/ds-test/src/
forge-std/=lib/forge-std/src/
src/=src/
pt-v5-liquidator-interfaces=lib/pt-v5-liquidator-interfaces/src/
pt-v5-prize-pool=lib/pt-v5-prize-pool/src/
16 changes: 0 additions & 16 deletions script/Foo.s.sol

This file was deleted.

63 changes: 63 additions & 0 deletions src/FeeBurner.sol
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { ILiquidationSource } from "pt-v5-liquidator-interfaces/interfaces/ILiquidationSource.sol";
import { PrizePool } from "pt-v5-prize-pool/PrizePool.sol";

contract FeeBurner is ILiquidationSource {

address public constant DEAD_ADDRESS = 0x000000000000000000000000000000000000dEaD;

PrizePool public immutable prizePool;
address public immutable burnToken;
address public immutable liquidationPair;

constructor(PrizePool _prizePool, address _burnToken, address _liquidationPair) {
prizePool = _prizePool;
liquidationPair = _liquidationPair;
burnToken = _burnToken;

emit LiquidationPairSet(address(prizePool.prizeToken()), _liquidationPair);
}

function liquidatableBalanceOf(address tokenOut) external returns (uint256) {
if (tokenOut != address(prizePool.prizeToken())) {
return 0;
}
return prizePool.rewardBalance(address(this));
}

function transferTokensOut(
address sender,
address receiver,
address tokenOut,
uint256 amountOut
) external onlyLiquidationPair returns (bytes memory) {
require(tokenOut == address(prizePool.prizeToken()), "FeeBurner: Invalid tokenOut");
prizePool.withdrawRewards(receiver, amountOut);
}

function verifyTokensIn(
address tokenIn,
uint256 amountIn,
bytes calldata transferTokensOutData
) external {
require(tokenIn == burnToken, "FeeBurner: Invalid tokenIn");
}

function targetOf(address tokenIn) external returns (address) {
return DEAD_ADDRESS;
}

function isLiquidationPair(address _tokenOut, address _liquidationPair) external returns (bool) {
if (_tokenOut != address(prizePool.prizeToken())) {
return false;
}
return liquidationPair == _liquidationPair;
}

modifier onlyLiquidationPair() {
require(msg.sender == liquidationPair, "FeeBurner: Only liquidation pair");
_;
}
}
91 changes: 91 additions & 0 deletions src/FeeBurnerFactory.sol
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { IERC20, IERC4626 } from "openzeppelin/token/ERC20/extensions/ERC4626.sol";
import { PrizePool } from "pt-v5-prize-pool/PrizePool.sol";

import { FeeBurner } from "./FeeBurner.sol";

/**
* @title PoolTogether V5 Prize Vault Factory
* @author PoolTogether Inc. & G9 Software Inc.
* @notice Factory contract for deploying new prize vaults using a standard underlying ERC4626 yield vault.
*/
contract FeeBurnerFactory {
/* ============ Events ============ */

/**
* @notice Emitted when a new FeeBurner has been deployed by this factory.
* @param feeBurner The Fee Burner that was created
* @param prizePool The prize pool the vault contributes to
*/
event NewFeeBurner(
FeeBurner indexed feeBurner,
PrizePool indexed prizePool
);

/* ============ Variables ============ */

/// @notice List of all vaults deployed by this factory.
FeeBurner[] public allFeeBurners;

/// @notice Mapping to verify if a Vault has been deployed via this factory.
mapping(address vault => bool deployedByFactory) public deployedFeeBurners;

/// @notice Mapping to store deployer nonces for CREATE2
mapping(address deployer => uint256 nonce) public deployerNonces;

/* ============ External Functions ============ */

/**
* @notice Deploy a new Fee Burner
* @return FeeBurner The newly deployed FeeBurner
*/
function deployFeeBurner(
PrizePool _prizePool,
address _burnToken,
address _liquidationPair
) external returns (FeeBurner) {
FeeBurner _feeBurner = new FeeBurner{
salt: keccak256(abi.encode(msg.sender, deployerNonces[msg.sender]++))
}(
_prizePool,
_burnToken,
_liquidationPair
);

allFeeBurners.push(_feeBurner);
deployedFeeBurners[address(_feeBurner)] = true;

emit NewFeeBurner(
_feeBurner,
_prizePool
);

return _feeBurner;
}

function computeDeploymentAddress(
PrizePool _prizePool,
address _burnToken,
address _liquidationPair
) external view returns (address) {
return address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
keccak256(abi.encode(msg.sender, deployerNonces[msg.sender])),
keccak256(abi.encodePacked(
type(FeeBurner).creationCode,
abi.encode(_prizePool, _burnToken, _liquidationPair)
))
)))));
}

/**
* @notice Total number of vaults deployed by this factory.
* @return uint256 Number of vaults deployed by this factory.
*/
function totalVaults() external view returns (uint256) {
return allFeeBurners.length;
}
}
8 changes: 0 additions & 8 deletions src/Foo.sol

This file was deleted.

19 changes: 19 additions & 0 deletions test/FeeBurner.t.sol
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.21;

import "forge-std/Test.sol";

import { FeeBurner } from "../src/FeeBurner.sol";

/// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge.
/// https://book.getfoundry.sh/forge/writing-tests
contract FeeBurnerTest is Test {

function setUp() public {
}

/// @dev Simple test. Run Forge with `-vvvv` to see stack traces.
function test() external {

}
}
39 changes: 39 additions & 0 deletions test/FeeBurnerFactory.t.sol
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.21;

import "forge-std/Test.sol";

import { PrizePool } from "pt-v5-prize-pool/PrizePool.sol";
import { FeeBurner } from "../src/FeeBurner.sol";
import { FeeBurnerFactory } from "../src/FeeBurnerFactory.sol";

/// @dev See the "Writing Tests" section in the Foundry Book if this is your first time with Forge.
/// https://book.getfoundry.sh/forge/writing-tests
contract FeeBurnerTest is Test {

FeeBurnerFactory factory;

PrizePool prizePool = PrizePool(makeAddr("prizePool"));
address burnToken = makeAddr("burnToken");
address prizeToken = makeAddr("prizeToken");
address liquidationPair = makeAddr("liquidationPair");

function setUp() public {
factory = new FeeBurnerFactory();
vm.mockCall(address(prizePool), abi.encodeWithSelector(prizePool.prizeToken.selector), abi.encode(prizeToken));
}

/// @dev Simple test. Run Forge with `-vvvv` to see stack traces.
function test() external {
address expectedAddress = factory.computeDeploymentAddress(prizePool, burnToken, liquidationPair);
FeeBurner burner = factory.deployFeeBurner(
prizePool,
burnToken,
liquidationPair
);
assertEq(address(burner), expectedAddress, "address was computed correctly");
assertEq(burner.burnToken(), burnToken, "burn token");
assertEq(address(burner.prizePool()), address(prizePool), "prize pool");
assertEq(burner.liquidationPair(), liquidationPair, "liquidation pair");
}
}
40 changes: 0 additions & 40 deletions test/Foo.t.sol

This file was deleted.

0 comments on commit bdaa90b

Please sign in to comment.