-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #124 from fei-protocol/feat/IndexOTC
INDEX OTC Proposal
- Loading branch information
Showing
15 changed files
with
699 additions
and
52 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
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
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
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,88 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity ^0.8.0; | ||
|
||
import "../PCVDeposit.sol"; | ||
|
||
interface DelegateRegistry { | ||
function setDelegate(bytes32 id, address delegate) external; | ||
|
||
function clearDelegate(bytes32 id) external; | ||
|
||
function delegation(address delegator, bytes32 id) external view returns(address delegatee); | ||
} | ||
|
||
/// @title Snapshot Delegator PCV Deposit | ||
/// @author Fei Protocol | ||
contract SnapshotDelegatorPCVDeposit is PCVDeposit { | ||
|
||
event DelegateUpdate(address indexed oldDelegate, address indexed newDelegate); | ||
|
||
/// @notice the Gnosis delegate registry used by snapshot | ||
DelegateRegistry public constant DELEGATE_REGISTRY = DelegateRegistry(0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446); | ||
|
||
/// @notice the token that is being used for snapshot | ||
IERC20 public immutable token; | ||
|
||
/// @notice the keccak encoded spaceId of the snapshot space | ||
bytes32 public spaceId; | ||
|
||
/// @notice the snapshot delegate for the deposit | ||
address public delegate; | ||
|
||
/// @notice Snapshot Delegator PCV Deposit constructor | ||
/// @param _core Fei Core for reference | ||
/// @param _token snapshot token | ||
/// @param _spaceId the id (or ENS name) of the snapshot space | ||
constructor( | ||
address _core, | ||
IERC20 _token, | ||
bytes32 _spaceId, | ||
address _initialDelegate | ||
) CoreRef(_core) { | ||
token = _token; | ||
spaceId = _spaceId; | ||
_delegate(_initialDelegate); | ||
} | ||
|
||
/// @notice withdraw tokens from the PCV allocation | ||
/// @param amountUnderlying of tokens withdrawn | ||
/// @param to the address to send PCV to | ||
function withdraw(address to, uint256 amountUnderlying) | ||
external | ||
override | ||
onlyPCVController | ||
{ | ||
_withdrawERC20(address(token), to, amountUnderlying); | ||
} | ||
|
||
/// @notice no-op | ||
function deposit() external override {} | ||
|
||
/// @notice returns total balance of PCV in the Deposit | ||
function balance() public view override returns (uint256) { | ||
return token.balanceOf(address(this)); | ||
} | ||
|
||
/// @notice sets the snapshot delegate | ||
/// @dev callable by governor or admin | ||
function setDelegate(address newDelegate) external onlyGovernorOrAdmin { | ||
_delegate(newDelegate); | ||
} | ||
|
||
/// @notice clears the delegate from snapshot | ||
/// @dev callable by governor or guardian | ||
function clearDelegate() external onlyGuardianOrGovernor { | ||
address oldDelegate = delegate; | ||
DELEGATE_REGISTRY.clearDelegate(spaceId); | ||
|
||
emit DelegateUpdate(oldDelegate, address(0)); | ||
} | ||
|
||
function _delegate(address newDelegate) internal { | ||
address oldDelegate = delegate; | ||
DELEGATE_REGISTRY.setDelegate(spaceId, newDelegate); | ||
delegate = newDelegate; | ||
|
||
emit DelegateUpdate(oldDelegate, newDelegate); | ||
} | ||
} |
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,68 @@ | ||
|
||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity ^0.8.4; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
|
||
/* | ||
Simple OTC Escrow contract to transfer tokens OTC | ||
Inspired and forked from BadgerDAO | ||
https://github.com/Badger-Finance/badger-system/blob/develop/contracts/badger-timelock/OtcEscrow.sol | ||
*/ | ||
contract OtcEscrow { | ||
using SafeERC20 for IERC20; | ||
|
||
address public receivedToken; | ||
address public sentToken; | ||
address public recipient; | ||
|
||
address public beneficiary; | ||
uint256 public receivedAmount; | ||
uint256 public sentAmount; | ||
|
||
constructor( | ||
address beneficiary_, | ||
address recipient_, | ||
address receivedToken_, | ||
address sentToken_, | ||
uint256 receivedAmount_, | ||
uint256 sentAmount_ | ||
) { | ||
beneficiary = beneficiary_; | ||
recipient = recipient_; | ||
|
||
receivedToken = receivedToken_; | ||
sentToken = sentToken_; | ||
|
||
receivedAmount = receivedAmount_; | ||
sentAmount = sentAmount_; | ||
} | ||
|
||
modifier onlyApprovedParties() { | ||
require(msg.sender == recipient || msg.sender == beneficiary); | ||
_; | ||
} | ||
|
||
/// @dev Atomically trade specified amount of receivedToken for control over sentToken in vesting contract | ||
/// @dev Either counterparty may execute swap if sufficient token approval is given by recipient | ||
function swap() public onlyApprovedParties { | ||
// Transfer expected receivedToken from beneficiary | ||
IERC20(receivedToken).safeTransferFrom(beneficiary, recipient, receivedAmount); | ||
|
||
// Transfer sentToken to beneficiary | ||
IERC20(sentToken).safeTransfer(address(beneficiary), sentAmount); | ||
} | ||
|
||
/// @dev Return sentToken to Fei Protocol to revoke escrow deal | ||
function revoke() external { | ||
require(msg.sender == recipient, "onlyRecipient"); | ||
uint256 sentTokenBalance = IERC20(sentToken).balanceOf(address(this)); | ||
IERC20(sentToken).safeTransfer(recipient, sentTokenBalance); | ||
} | ||
|
||
function revokeReceivedToken() external onlyApprovedParties { | ||
uint256 receivedTokenBalance = IERC20(receivedToken).balanceOf(address(this)); | ||
IERC20(receivedToken).safeTransfer(beneficiary, receivedTokenBalance); | ||
} | ||
} |
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
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,78 @@ | ||
import { formatBytes32String } from '@ethersproject/strings'; | ||
|
||
const OtcEscrow = artifacts.require('OtcEscrow'); | ||
const SnapshotDelegatorPCVDeposit = artifacts.require('SnapshotDelegatorPCVDeposit'); | ||
|
||
const e18 = '000000000000000000'; | ||
const e15 = '000000000000000'; | ||
const indexSpaceId = formatBytes32String('index-coop.eth'); | ||
const indexDelegate = '0xb647055A9915bF9c8021a684E175A353525b9890'; // Matthew Graham delegation | ||
|
||
async function deploy(deployAddress, addresses, logging = false) { | ||
const { | ||
coreAddress, | ||
feiAddress, | ||
wethAddress, | ||
tribeAddress, | ||
indexAddress, | ||
defiPulseOTCAddress, | ||
timelockAddress | ||
} = addresses; | ||
|
||
if ( | ||
!coreAddress || !wethAddress || !feiAddress || !tribeAddress || !indexAddress || !defiPulseOTCAddress | ||
) { | ||
throw new Error('An environment variable contract address is not set'); | ||
} | ||
|
||
const ethOTCEscrow = await OtcEscrow.new( | ||
defiPulseOTCAddress, | ||
timelockAddress, | ||
indexAddress, | ||
wethAddress, | ||
`50000${e18}`, // 50k INDEX | ||
`633150${e15}`, // 633.150 ETH | ||
{ from: deployAddress } | ||
); | ||
logging ? console.log('ETH OTC Escrow deployed to: ', ethOTCEscrow.address) : undefined; | ||
|
||
const tribeOTCEscrow = await OtcEscrow.new( | ||
defiPulseOTCAddress, | ||
timelockAddress, | ||
indexAddress, | ||
tribeAddress, | ||
`25000${e18}`, // 25k INDEX | ||
`1235325922${e15}`, // 1235325.922 TRIBE | ||
{ from: deployAddress } | ||
); | ||
logging ? console.log('TRIBE OTC Escrow deployed to: ', tribeOTCEscrow.address) : undefined; | ||
|
||
const feiOTCEscrow = await OtcEscrow.new( | ||
defiPulseOTCAddress, | ||
timelockAddress, | ||
indexAddress, | ||
feiAddress, | ||
`25000${e18}`, // 25k INDEX | ||
`991512900${e15}`, // 991512.900 FEI | ||
{ from: deployAddress } | ||
); | ||
logging ? console.log('FEI OTC Escrow deployed to: ', feiOTCEscrow.address) : undefined; | ||
|
||
const indexDelegator = await SnapshotDelegatorPCVDeposit.new( | ||
coreAddress, | ||
indexAddress, | ||
indexSpaceId, | ||
indexDelegate | ||
); | ||
|
||
logging ? console.log('Index Delegator deployed to: ', indexDelegator.address) : undefined; | ||
|
||
return { | ||
ethOTCEscrow, | ||
tribeOTCEscrow, | ||
feiOTCEscrow, | ||
indexDelegator | ||
}; | ||
} | ||
|
||
module.exports = { deploy }; |
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
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
Oops, something went wrong.