proposal & auction vesting

This commit is contained in:
gozzy 2023-03-15 18:07:13 +00:00
parent 6e9bbaae8d
commit 71222d5759
8 changed files with 145 additions and 157 deletions

View File

@ -1,42 +0,0 @@
import "@nomiclabs/hardhat-waffle"
import "@nomiclabs/hardhat-truffle5"
import * as dotenv from "dotenv"
import { HardhatUserConfig } from "hardhat/types"
import { solConfig } from './utils/constants'
import { task } from "hardhat/config"
dotenv.config({
path: `${__dirname}/.configuration.env`
})
let configuration: HardhatUserConfig = {
networks: {
hardhat: {
blockGasLimit: 9500000
}
},
solidity: {
compilers: [
{
version: "0.8.0",
settings: solConfig
}
],
},
mocha: {
timeout: 500000
}
}
if(process.env.NETWORK){
configuration.networks[process.env.NETWORK] = {
url: `${process.env.RPC_ENDPOINT}`,
accounts: [
`0x${process.env.PRIVATE_KEY}`
]
}
}
export default configuration

View File

@ -46,6 +46,7 @@ contract DelegatedInstance {
bytes32 s bytes32 s
) external isSpender { ) external isSpender {
IERC20(_tokenAddress).transferFrom(msg.sender, address(this), amount); IERC20(_tokenAddress).transferFrom(msg.sender, address(this), amount);
IERC20(_tokenAddress).approve(_governanceAddress, amount);
IGovernance(_governanceAddress).lock(address(this), amount, deadline, v, r, s); IGovernance(_governanceAddress).lock(address(this), amount, deadline, v, r, s);
IGovernance(_governanceAddress).delegate(to); IGovernance(_governanceAddress).delegate(to);
} }
@ -60,7 +61,6 @@ contract DelegatedInstance {
IGovernance(_governanceAddress).unlock(stake); IGovernance(_governanceAddress).unlock(stake);
IStaking(_stakingAddress).getReward(); IStaking(_stakingAddress).getReward();
IERC20(_tokenAddress).transfer(_spender, stake + reward); IERC20(_tokenAddress).transfer(_spender, stake + reward);
} }
@ -68,86 +68,85 @@ contract DelegatedInstance {
contract DelegatedVesting { contract DelegatedVesting {
uint256 public _period; uint256 public _period;
address public _governanceAddress; address public _governanceAddress;
address public _tokenAddress; address public _tokenAddress;
mapping(address => uint256) _balances; mapping(address => uint256) _balances;
mapping(address => address) _instances; mapping(address => address) _instances;
mapping(address => uint256) _commitments; mapping(address => uint256) _commitments;
constructor( constructor(
uint256 vestingDuration, uint256 vestingDuration,
address governanceAddress, address governanceAddress,
address tokenAddress address tokenAddress
) { ) {
_period = vestingDuration; _period = vestingDuration;
_tokenAddress = tokenAddress; _tokenAddress = tokenAddress;
_operatorAddress = msg.sender; _governanceAddress = governanceAddress;
_governanceAddress = governanceAddress;
}
function isActiveCommitment(address stakeholder) public view returns (bool) {
return _balances[stakeholder] > 0 && _commitments[stakeholder] > block.timestamp;
}
function isDelegatedCommitment(address stakeholder) public view returns (bool) {
return isActiveCommitment(stakeholder) && _instances[stakeholder] != address(0x0);
}
function isFulfilledCommitment(address stakeholder) public view returns (bool) {
return _balances[stakeholder] > 0 && _commitments[stakeholder] < block.timestamp;
}
function makeCommitment(address stakeholder, uint256 amount) public {
require(IERC20(_tokenAddress).transferFrom(msg.sender, address(this), amount));
_commitments[stakeholder] = block.timestmap + _period;
_balances[stakeholder] += amount;
}
function delegateCommitment(
address delegateAddress,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public {
require(isActiveCommitment(msg.sender), "INVALID COMMITMENT");
if(isDelegatedCommitment(msg.sender)) {
DelegatedInstance(_instance[msg.sender]).delegate(delegateAddress);
} else {
DelegatedInstance e = new DelegatedInstance(
msg.sender,
_governanceAddress,
_tokenAddress,
_balances[msg.sender],
deadline,
v, r, s
);
_instances[msg.sender] = address(e);
IERC20(_tokenAddress).approve(address(e), _balances[msg.sender]);
e.lockAndDelegate(delegateAddress, _balances[msg.sender], deadline, v, r, s);
} }
}
function fulfillCommitment() public { function isActiveCommitment(address stakeholder) public view returns (bool) {
require(isFulfilledCommitment(msg.sender), "INVALID FULFILLMENT"); return _balances[stakeholder] > 0 && _commitments[stakeholder] > block.timestamp;
}
uint256 stake = _balances[msg.sender];
address delegated = _instances[msg.sender]; function isDelegatedCommitment(address stakeholder) public view returns (bool) {
return isActiveCommitment(stakeholder) && _instances[stakeholder] != address(0x0);
delete _balances[msg.sender]; }
delete _instances[msg.sender];
function isFulfilledCommitment(address stakeholder) public view returns (bool) {
if(delegated != address(0x0)){ return _balances[stakeholder] > 0 && _commitments[stakeholder] < block.timestamp;
DelegatedInstance(delegated).unlockAndRedeem(); }
} else {
IERC20(_tokenAddress).transfer(msg.sender, stake); function makeCommitment(address stakeholder, uint256 amount) public {
require(IERC20(_tokenAddress).transferFrom(msg.sender, address(this), amount));
_commitments[stakeholder] = block.timestmap + _period;
_balances[stakeholder] += amount;
}
function delegateCommitment(
address delegateAddress,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public {
require(isActiveCommitment(msg.sender), "INVALID COMMITMENT");
if(isDelegatedCommitment(msg.sender)) {
DelegatedInstance(_instance[msg.sender]).delegate(delegateAddress);
} else {
DelegatedInstance e = new DelegatedInstance(
msg.sender,
_governanceAddress,
_tokenAddress,
_balances[msg.sender],
deadline,
v, r, s
);
_instances[msg.sender] = address(e);
IERC20(_tokenAddress).approve(address(e), _balances[msg.sender]);
e.lockAndDelegate(delegateAddress, _balances[msg.sender], deadline, v, r, s);
}
}
function fulfillCommitment() public {
require(isFulfilledCommitment(msg.sender), "INVALID FULFILLMENT");
uint256 stake = _balances[msg.sender];
address delegated = _instances[msg.sender];
delete _balances[msg.sender];
delete _instances[msg.sender];
if(delegated != address(0x0)){
DelegatedInstance(delegated).unlockAndRedeem();
} else {
IERC20(_tokenAddress).transfer(msg.sender, stake);
}
} }
}
} }

36
src/Proposal.sol Normal file
View File

@ -0,0 +1,36 @@
pragma solidity 0.8.0;
import "@root/interfaces/IERC20.sol";
import "@root/interfaces/IRollingDutchAuction.sol";
contract Proposal {
function executeProposal() external {
uint256 AUCTION_START_TS = block.timestamp;
uint256 AUCTION_END_TS = AUCTION_START_TS + 1 week;
uint256 AUCTION_ORIGIN_PRICE = 4172000 gwei;
uint256 AUCTION_RESERVE_AMOUNT = 100000 ether;
uint256 AUCTION_MINIMUM_AMOUNT = 1 ether;
uint256 AUCTION_WINDOW_LENGTH = 8 hours;
address wethAddress;
address tokenAddress;
address governanceAddress;
address auctionAddress;
address vestingAddress;
IRollingDutchAuction(auctionAddress).createAuction(
vestingAddress,
governanceAddress,
tokenAddress,
wethAddress,
AUCTION_RESERVE_AMOUNT,
AUCTION_MINIMUM_AMOUNT,
AUCTION_ORIGIN_PRICE,
AUCTION_START_TS,
AUCTION_END_TS,
AUCTION_WINDOW_LENGTH
);
}
}

View File

@ -2,6 +2,7 @@ pragma solidity 0.8.13;
import { UD60x18 } from "@prb/math/UD60x18.sol"; import { UD60x18 } from "@prb/math/UD60x18.sol";
import { IERC20 } from "@root/interfaces/IERC20.sol"; import { IERC20 } from "@root/interfaces/IERC20.sol";
import { IVesting } from "@root/interfaces/IVesting.sol";
import { inv, add, sub, mul, exp, ln, wrap, unwrap, gte, mod, div } from "@prb/math/UD60x18.sol"; import { inv, add, sub, mul, exp, ln, wrap, unwrap, gte, mod, div } from "@prb/math/UD60x18.sol";
@ -26,6 +27,7 @@ contract RollingDutchAuction {
mapping(bytes => uint256) public _windows; mapping(bytes => uint256) public _windows;
struct Auction { struct Auction {
address vestingAddress;
uint256 windowDuration; /* @dev Unix time window duration */ uint256 windowDuration; /* @dev Unix time window duration */
uint256 windowTimestamp; /* @dev Unix timestamp for window start */ uint256 windowTimestamp; /* @dev Unix timestamp for window start */
uint256 startTimestamp; /* @dev Unix auction start timestamp */ uint256 startTimestamp; /* @dev Unix auction start timestamp */
@ -114,6 +116,7 @@ contract RollingDutchAuction {
* @param w͟i͟n͟d͟o͟w͟D͟u͟r͟a͟t͟i͟o͟n͟ Uinx time window duration * @param w͟i͟n͟d͟o͟w͟D͟u͟r͟a͟t͟i͟o͟n͟ Uinx time window duration
*/ */
function createAuction( function createAuction(
address vestingAddress,
address operatorAddress, address operatorAddress,
address reserveToken, address reserveToken,
address purchaseToken, address purchaseToken,
@ -129,7 +132,7 @@ contract RollingDutchAuction {
reserveToken, reserveToken,
purchaseToken, purchaseToken,
minimumPurchaseAmount, minimumPurchaseAmount,
abi.encodePacked(reserveAmount, startingPrice, startTimestamp, endTimestamp, windowDuration) abi.encodePacked(reserveAmount, startingOriginPrice, startTimestamp, endTimestamp, windowDuration)
); );
Auction storage state = _auctions[auctionId]; Auction storage state = _auctions[auctionId];
@ -138,6 +141,7 @@ contract RollingDutchAuction {
IERC20(reserveToken).transferFrom(msg.sender, address(this), reserveAmount); IERC20(reserveToken).transferFrom(msg.sender, address(this), reserveAmount);
state.vestingAddress = vestingAddress;
state.duration = endTimestamp - startTimestamp; state.duration = endTimestamp - startTimestamp;
state.windowDuration = windowDuration; state.windowDuration = windowDuration;
state.windowTimestamp = startTimestamp; state.windowTimestamp = startTimestamp;
@ -146,7 +150,7 @@ contract RollingDutchAuction {
state.price = startingOriginPrice; state.price = startingOriginPrice;
state.reserves = reserveAmount; state.reserves = reserveAmount;
emit NewAuction(auctionId, reserveToken, reserveAmount, startingPrice, endTimestamp); emit NewAuction(auctionId, reserveToken, reserveAmount, startingOriginPrice, endTimestamp);
return auctionId; return auctionId;
} }
@ -386,7 +390,7 @@ contract RollingDutchAuction {
IERC20(purchaseToken(auctionId)).transfer(bidder, refund); IERC20(purchaseToken(auctionId)).transfer(bidder, refund);
} }
if (claim > 0) { if (claim > 0) {
IERC20(reserveToken(auctionId)).transfer(bidder, claim); IVesting(_auctions[auctionId].vestingAddress).makeCommitment(bidder, claim);
} }
emit Claim(auctionId, claimHash); emit Claim(auctionId, claimHash);

View File

@ -0,0 +1,22 @@
pragma solidity 0.8.0;
interface IRollingDutchAuction {
function createAuction(
address vestingAddress,
address operatorAddress,
address reserveToken,
address purchaseToken,
uint256 reserveAmount,
uint256 minimumPurchaseAmount,
uint256 startingOriginPrice,
uint256 startTimestamp,
uint256 endTimestamp,
uint256 windowDuration
) external returns (bytes memory);
function withdraw(bytes memory auctionId) external;
function redeem(address bidder, bytes memory auctionId external);
}

View File

@ -0,0 +1,7 @@
pragma solidity 0.8.0;
interface IVesting {
function makeCommitment(address stakeholder, uint256 amount) external;
}

View File

@ -1,32 +0,0 @@
{
"files": ["./hardhat.config.ts"],
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"noImplicitAny": false,
"moduleResolution": "node",
"resolveJsonModule": true,
"esModuleInterop": true,
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
},
"exclude": [
"node_modules/",
"contracts/",
],
"include": [
"types.d.ts",
"hre.d.ts",
"utils/",
"tests/"
],
"types": [
"jest",
"node"
]
}

View File

@ -1,6 +0,0 @@
export const solConfig = {
optimizer: {
enabled: true,
runs: 200,
}
}