Skip to content

Commit

Permalink
Rebrand OGV contracts and tweak Governance parameters (#406)
Browse files Browse the repository at this point in the history
  • Loading branch information
shahthepro committed Nov 27, 2023
1 parent d420f0f commit 5a6ed04
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 33 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ jobs:

- name: Install Requirements
run: pip install -r requirements.txt

- name: Create .env
run: touch .env

- name: Run tests
run: brownie test --network hardhat
Expand Down
1 change: 1 addition & 0 deletions brownie-config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dotenv: .env
dependencies:
- OpenZeppelin/openzeppelin-contracts@4.6.0
- OpenZeppelin/openzeppelin-contracts-upgradeable@4.6.0
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions build/deployments/map.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
"0x9c354503C38481a7A7a51629142963F98eCC12D0"
],
"Governance": [
"0xC6a3525e2FD8F4844a6fdfE4552a583CE5aC7EfA",
"0x3cdD07c16614059e66344a7b579DAB4f9516C0b6"
"0x3cdD07c16614059e66344a7b579DAB4f9516C0b6",
"0xC6a3525e2FD8F4844a6fdfE4552a583CE5aC7EfA"
],
"MandatoryLockupDistributor": [
"0xD667091c2d1DCc8620f4eaEA254CdFB0a176718D"
],
"OgvStaking": [
"0xFd8e7DAcC16c3807E66FEdD4F7c65f26B1fEE558",
"0xE61110663334794abA03c349c621A075DC590a42",
"0xe61110663334794aba03c349c621a075dc590a42"
],
Expand All @@ -22,6 +23,7 @@
"0x7aE2334f12a449895AD21d4c255D9DE194fe986f"
],
"OriginDollarGovernance": [
"0x190140d8D1815f6f92FD58DF0dacB758276fFFDB",
"0x7DFAFe7d547Fc9083719D633B9c5f6f542C42c77",
"0xEd6E3808FCe0C4A52DEa8636933f666c6dea4d1d",
"0x6cE89Ff1E8a910007BAc236C27B88f8a95B0bFaD"
Expand All @@ -33,8 +35,8 @@
"0x7d82E86CF1496f9485a8ea04012afeb3C7489397"
],
"Timelock": [
"0xac126C98cFc7c55a9F944770cb17d7065688C577",
"0x35918cDE7233F2dD33fA41ae3Cb6aE0e42E0e69F"
"0x35918cDE7233F2dD33fA41ae3Cb6aE0e42E0e69F",
"0xac126C98cFc7c55a9F944770cb17d7065688C577"
]
},
"4": {
Expand Down
67 changes: 53 additions & 14 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from brownie import *
import brownie

BLOCKS_PER_DAY = 86400 / 12 # 12 blocks per second

STRATEGIST = '0xF14BBdf064E3F67f51cd9BD646aE3716aD938FDC'
GOV_MULTISIG = '0xbe2AB3d3d8F6a32b96414ebbd865dBD276d3d899'
GOVERNOR_FIVE = '0x3cdd07c16614059e66344a7b579dab4f9516c0b6'
Expand All @@ -28,24 +30,61 @@ def governanceProposal(deployment):
return

actions = deploymentInfo['actions']
print('Executing governance proposal')

if (len(actions) > 0):
ogvGovernor = Contract.from_explorer(GOVERNOR_FIVE)
with TemporaryFork():
propose_tx = ogvGovernor.propose(
[action['contract'].address for action in actions],
[0 for action in actions],
[action['signature'] for action in actions],
# To explain this code salad:
# - action['signature'][:action['signature'].index('(')] -> this part gets the function name from signature
# - encode_input(*action['args']) -> encodes said function data
# - [10:] trim first 10 character to trim function name signature away from data
[getattr(action['contract'], action['signature'][:action['signature'].index('(')]).encode_input(*action['args'])[10:] for action in actions],
deploymentInfo['name'],
proposal_args = [
[action['contract'].address for action in actions],
[0 for action in actions],
[action['signature'] for action in actions],
# To explain this code salad:
# - action['signature'][:action['signature'].index('(')] -> this part gets the function name from signature
# - encode_input(*action['args']) -> encodes said function data
# - [10:] trim first 10 character to trim function name signature away from data
[getattr(action['contract'], action['signature'][:action['signature'].index('(')]).encode_input(*action['args'])[10:] for action in actions],
deploymentInfo['name'],
]

if is_fork:
print('Creating governance proposal on fork')
ogvGovernor.propose(
*proposal_args,
{'from': GOV_MULTISIG}
)
# Simulate execution on fork
proposalId = propose_tx.events['ProposalCreated'][0][0]['proposalId']

# Move forward 30s so that we can vote
timetravel(30)

# Vote on Proposal
print("Voting on the proposal")
ogvGovernor.castVote(proposalId, 1, {'from': GOV_MULTISIG})

# 3 days to queue (+2 for buffer since contract has a different BLOCKS_PER_DAY now)
timetravel(86400 * 5)

print("Queueing proposal")
ogvGovernor.queue(proposalId, {'from': GOV_MULTISIG})

# 2 day timelock (+1 day for buffer)
timetravel(86400 * 3)

print("Executing proposal")
ogvGovernor.execute(proposalId, {'from': GOV_MULTISIG})

else:
propose_data = ogvGovernor.propose.encode_input(
*proposal_args
)

print("Raw Args", proposal_args)

print("Execute the following transaction to create OGV Governance proposal")
print("To: {}".format(propose_tx.receiver))
print("Data: {}".format(propose_tx.input))
print("To: {}".format(GOVERNOR_FIVE))
print("Data: {}".format(propose_data))


def timetravel(seconds):
brownie.chain.sleep(seconds + 1)
brownie.chain.mine(int(seconds / BLOCKS_PER_DAY) + 1)
4 changes: 4 additions & 0 deletions contracts/GovernanceToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ contract OriginDollarGovernance is
override
onlyOwner
{}

function name() public view virtual override returns (string memory) {
return "Origin DeFi Governance";
}
}
2 changes: 1 addition & 1 deletion contracts/OgvStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ contract OgvStaking is ERC20Votes {
}

function name() public pure override returns (string memory) {
return "Vote Escrowed Origin Dollar Governance";
return "Vote Escrowed Origin DeFi Governance";
}

function symbol() public pure override returns (string memory) {
Expand Down
72 changes: 72 additions & 0 deletions scripts/deploy_005_rebranding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import os

from brownie import *
from brownie.network import priority_fee
from common import *

OGV_PROXY_ADDRESS = "0x9c354503c38481a7a7a51629142963f98ecc12d0"
VEOGV_PROXY_ADDRESS = "0x0c4576ca1c365868e162554af8e385dc3e7c66d9"
REWARDS_PROXY_ADDRESS = "0x7d82e86cf1496f9485a8ea04012afeb3c7489397"
GOVERNANCE_ADDRESS = "0x3cdd07c16614059e66344a7b579dab4f9516c0b6"

def main():
def deployment(deployer, FROM_DEPLOYER, local_provider, is_mainnet, is_fork, is_proposal_mode):
# Existing contracts
veogv_proxy = Contract.from_abi("OgvStakingProxy", VEOGV_PROXY_ADDRESS, OgvStakingProxy.abi)
ogv_proxy = Contract.from_abi("OriginDollarGovernance", OGV_PROXY_ADDRESS, OriginDollarGovernance.abi)
governance = Contract.from_abi("Governance", GOVERNANCE_ADDRESS, Governance.abi)

if not is_fork:
# Dynamicly price gas, avoids over paying or TX's getting stuck
priority_fee("2 gwei")

# these values are marked as immutable in the contract and for that reason
# the compiler does not reserve storage slots for them - rather they are
# copied to all the places in the code where they are used. It is important
# that we use the correct values in the constructor
#
# https://docs.soliditylang.org/en/v0.8.17/contracts.html#constant-and-immutable-state-variables
min_staking = 30 * 24 * 60 * 60 # 2592000 -> 30 days
epoch = 1657584000

# Deploy new implementations
veogv_impl = OgvStaking.deploy(OGV_PROXY_ADDRESS, epoch, min_staking, REWARDS_PROXY_ADDRESS, FROM_DEPLOYER)
print("OGVStaking Implementation deployed at {}".format(veogv_impl.address))

ogv_impl = OriginDollarGovernance.deploy(FROM_DEPLOYER)
print("OriginDollarGovernance Implementation deployed at {}".format(ogv_impl.address))

if is_mainnet:
# Verify contract on etherscan on mainnet
print("Verifying contract on Etherscan...")

OgvStaking.publish_source(veogv_impl)
OriginDollarGovernance.publish_source(ogv_impl)

return {
'name': 'Rebrand OGV contracts and adjust governance parameters',
'actions': [
{
'contract': veogv_proxy,
'signature': 'upgradeTo(address)',
'args': [veogv_impl.address]
},
{
'contract': ogv_proxy,
'signature': 'upgradeTo(address)',
'args': [ogv_impl.address]
},
{
'contract': governance,
'signature': 'setVotingPeriod(uint256)',
'args': [BLOCKS_PER_DAY * 2] # 2 days
},
{
'contract': governance,
'signature': 'setLateQuorumVoteExtension(uint64)',
'args': [BLOCKS_PER_DAY * 1] # 1 day
},
]
}

governanceProposal(deployment)
23 changes: 9 additions & 14 deletions tests/test_token.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,55 @@
import brownie
from brownie import *
from .fixtures import token

from .fixtures import token, staking, rewards

def test_name(token):
assert token.name() == "Origin Dollar Governance"

assert token.name() == "Origin DeFi Governance"

def test_symbol(token):
assert token.symbol() == "OGV"

def test_staking_name(staking):
assert staking.name() == "Vote Escrowed Origin DeFi Governance"

def test_staking_symbol(staking):
assert staking.symbol() == "veOGV"

def test_decimals(token):
assert token.decimals() == 18


def test_initial_total_supply(token):
assert token.totalSupply() == 1000000000 * 10**18


def test_owner(token):
assert token.owner() == accounts[0]


def test_transfer_ownership(token):
token.transferOwnership(accounts[1])
assert token.owner() == accounts[1]


def test_non_owner_cant_mint(token):
with brownie.reverts(
"AccessControl: account "+accounts[1].address.lower()+" is missing role 0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6"
):
token.mint(accounts[1], 100, {"from": accounts[1]})


def test_minter_can_mint(token):
token.grantMinterRole(accounts[0], {"from": accounts[0]})
token.mint(accounts[1], 100, {"from": accounts[0]})
assert token.totalSupply() == 1000000000 * 10**18 + 100


def test_cant_upgrade_to_non_uups(token):
non_uups_token = NonUUPSToken.deploy({"from": accounts[0]})
with brownie.reverts("ERC1967Upgrade: new implementation is not UUPS"):
token.upgradeTo(non_uups_token.address)


def test_upgrade(token):
upgrade_to = TestToken.deploy({"from": accounts[0]})
token.upgradeTo(upgrade_to.address)
token = Contract.from_abi("TestToken", token.address, upgrade_to.abi)
with brownie.reverts("Upgraded"):
token.proof()


def test_non_owner_cant_upgrade(token):
upgrade_to = TestToken.deploy({"from": accounts[0]})
with brownie.reverts("Ownable: caller is not the owner"):
Expand All @@ -69,7 +64,7 @@ def test_burn_from(token):
alice = accounts[0]
bob = accounts[1]

before_balance = token.balanceOf(alice);
before_balance = token.balanceOf(alice)
token.approve(bob, 100, {'from': alice})
token.burnFrom(alice, 100, {'from': bob})
assert before_balance - 100 == token.balanceOf(alice)
Expand All @@ -78,7 +73,7 @@ def test_burn_from_fail_not_approved(token):
alice = accounts[0]
bob = accounts[1]

before_balance = token.balanceOf(alice);
before_balance = token.balanceOf(alice)
token.approve(bob, 90, {'from': alice})
with brownie.reverts("ERC20: insufficient allowance"):
token.burnFrom(alice, 100, {'from': bob})

0 comments on commit 5a6ed04

Please sign in to comment.