diff --git a/data/badger/timelock/upgrade_remBadger_2_0/0xa70e564d8e6c4bbc5612ece25c89a557fea4e70ff424d414e340be8eb76408bb.json b/data/badger/timelock/upgrade_remBadger_2_0/0xa70e564d8e6c4bbc5612ece25c89a557fea4e70ff424d414e340be8eb76408bb.json new file mode 100644 index 00000000..d3c84c1b --- /dev/null +++ b/data/badger/timelock/upgrade_remBadger_2_0/0xa70e564d8e6c4bbc5612ece25c89a557fea4e70ff424d414e340be8eb76408bb.json @@ -0,0 +1,7 @@ +{ + "data": "0000000000000000000000006af7377b5009d7d154f36fe9e235ae1da27aea22000000000000000000000000eeff9a69febaeae39883dbea1eb12db367b97120", + "eta": 1715651201, + "eth": 0, + "signature": "upgrade(address,address)", + "target": "0x20Dce41Acca85E8222D6861Aa6D23B6C941777bF" +} \ No newline at end of file diff --git a/helpers/addresses.py b/helpers/addresses.py index 1fdf1ce4..811be54a 100644 --- a/helpers/addresses.py +++ b/helpers/addresses.py @@ -25,6 +25,7 @@ "aragon_voting": "0xDc344bFB12522bF3fa58EF0d6b9a41256fc79A1b", "badger_voting_shares": "0x49fa0D0619BdeD9aAc4106974E34CeB516bdeAeF", "brickedProxyAdmin": "0x933FDBAc3773514384c6db30Eb196a0be543D617", + "brembadger": "0x170D9fA0Cb0226f0d87952905228e5AA7323DdA6", "drippers": { "rembadger_2022_q2": "0xD87F434fE6d5B349f4376d2daBA762b213E403c7", "tree_2022_q2": "0xfA55d407F48849aE98a6e4f11Dc5C18E035F46Ec", diff --git a/helpers/utils.py b/helpers/utils.py new file mode 100644 index 00000000..d232cbc3 --- /dev/null +++ b/helpers/utils.py @@ -0,0 +1,7 @@ +def approx(actual, expected, percentage_threshold): + print(actual, expected, percentage_threshold) + diff = int(abs(actual - expected)) + # 0 diff should automtically be a match + if diff == 0: + return True + return diff < (actual * percentage_threshold // 100) diff --git a/interfaces/badger/IbremBadger.sol b/interfaces/badger/IbremBadger.sol new file mode 100644 index 00000000..44793dfe --- /dev/null +++ b/interfaces/badger/IbremBadger.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: UNLICENSED +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.8.0. SEE SOURCE BELOW. !! +pragma solidity ^0.8.20; + +interface IbremBadger { + error AddressEmptyCode(address target); + error AddressInsufficientBalance(address account); + error ERC1967InvalidImplementation(address implementation); + error ERC1967NonPayable(); + error FailedInnerCall(); + error InvalidInitialization(); + error NotInitializing(); + error ReentrancyGuardReentrantCall(); + error SafeERC20FailedOperation(address token); + error UUPSUnauthorizedCallContext(); + error UUPSUnsupportedProxiableUUID(bytes32 slot); + event DepositsDisabled(); + event DepositsEnabled(uint256 start, uint256 end); + event Initialized(uint64 version); + event Terminated(); + event Upgraded(address indexed implementation); + + function ADMIN() external view returns (address); + + function DEPOSIT_PERIOD_IN_SECONDS() external view returns (uint256); + + function ONE_WEEK_IN_SECONDS() external view returns (uint256); + + function OWNER() external view returns (address); + + function REM_BADGER_TOKEN() external view returns (address); + + function UNLOCK_TIMESTAMP() external view returns (uint256); + + function UPGRADE_INTERFACE_VERSION() external view returns (string memory); + + function VESTING_WEEKS() external view returns (uint256); + + function deposit(uint256 _amount) external; + + function depositEnd() external view returns (uint256); + + function depositStart() external view returns (uint256); + + function disableDeposits() external; + + function enableDeposits() external; + + function initialize() external; + + function proxiableUUID() external view returns (bytes32); + + function terminate() external; + + function terminated() external view returns (bool); + + function totalClaimed(address) external view returns (uint256); + + function totalDeposited(address) external view returns (uint256); + + function upgradeToAndCall(address newImplementation, bytes memory data) + external + payable; + + function vestedAmount(address _depositor) external view returns (uint256); + + function withdrawAll() external; +} \ No newline at end of file diff --git a/scripts/badger/restitution_2_0.py b/scripts/badger/restitution_2_0.py new file mode 100644 index 00000000..84f0933d --- /dev/null +++ b/scripts/badger/restitution_2_0.py @@ -0,0 +1,26 @@ +from helpers.addresses import r +from brownie import interface, chain +from great_ape_safe import GreatApeSafe + +TECHOPS = r.badger_wallets.techops_multisig +BREMBADGER = r.brembadger + + +def enable_deposits(): + safe = GreatApeSafe(TECHOPS) + + brembadger = safe.contract(BREMBADGER, interface.IbremBadger) + brembadger.enableDeposits() + assert brembadger.depositStart() == chain.time() + + safe.post_safe_tx() + + +def disable_deposits(): + safe = GreatApeSafe(TECHOPS) + + brembadger = safe.contract(BREMBADGER, interface.IbremBadger) + brembadger.disableDeposits() + assert brembadger.depositEnd() == chain.time() + + safe.post_safe_tx() diff --git a/scripts/issue/1518/upgrade_rembadger.py b/scripts/issue/1518/upgrade_rembadger.py index f0198a6f..02417075 100644 --- a/scripts/issue/1518/upgrade_rembadger.py +++ b/scripts/issue/1518/upgrade_rembadger.py @@ -1,5 +1,6 @@ from great_ape_safe import GreatApeSafe from helpers.addresses import registry +from helpers.utils import approx from brownie import accounts, interface, chain from rich.console import Console from eth_abi import encode_abi @@ -8,8 +9,10 @@ NEW_LOGIC = registry.eth.logic["remBadger"] DEV_PROXY = registry.eth.badger_wallets.devProxyAdmin -DEPOSIT_AMOUNT = 1788000000000000000000 # 1788 BADGER -DEPOSIT_USER = "0x138Dd537D56F2F2761a6fC0A2A0AcE67D55480FE" +USERS_AMOUNTS = { + "0x138Dd537D56F2F2761a6fC0A2A0AcE67D55480FE": 1788000000000000000000, # 1788 + "0x39e40AB1eAEc3daBd19c6830f24cF6342Df7f476": 11388000000000000000000, # 11,387 + 1 +} def queue(): @@ -65,11 +68,6 @@ def main(queue="true", simulation="false"): timelock = accounts.at(registry.eth.governance_timelock, force=True) proxyAdmin = interface.IProxyAdmin(DEV_PROXY, owner=timelock) proxyAdmin.upgrade(rembadger.address, NEW_LOGIC) - # Have user transfer BADGER to governance - user = accounts.at(DEPOSIT_USER, force=True) - assert badger.balanceOf(user) >= DEPOSIT_AMOUNT - badger.transfer(safe.account, DEPOSIT_AMOUNT, {"from": user}) - assert badger.balanceOf(safe.account) >= DEPOSIT_AMOUNT else: safe.badger.execute_timelock("data/badger/timelock/upgrade_remBadger_2_0/") @@ -95,21 +93,26 @@ def main(queue="true", simulation="false"): rembadger.enableDeposits() assert rembadger.depositsEnded() == False - # Governance deposits for user - assert badger.balanceOf(safe.account) >= DEPOSIT_AMOUNT - assert rembadger.balanceOf(DEPOSIT_USER) == 0 - badger.approve(rembadger, DEPOSIT_AMOUNT) - rembadger.depositFor(DEPOSIT_USER, DEPOSIT_AMOUNT) - C.print(f"User balance: {rembadger.balanceOf(DEPOSIT_USER)/1e18} remBADGER") - assert prev_balance + DEPOSIT_AMOUNT == rembadger.balance() - assert ( - prev_getPricePerFullShare == rembadger.getPricePerFullShare() - ) # PPFS do not increase with deposits - assert approx( - rembadger.balanceOf(DEPOSIT_USER), - (DEPOSIT_AMOUNT * 1e18) / prev_getPricePerFullShare, - 0.1, - ) + # Governance deposits for the userss + for deposit_user, deposit_amount in USERS_AMOUNTS.items(): + prev_balance = rembadger.balance() + prev_getPricePerFullShare = rembadger.getPricePerFullShare() + assert badger.balanceOf(safe.account) >= deposit_amount + assert rembadger.balanceOf(deposit_user) == 0 + + badger.approve(rembadger, deposit_amount) + rembadger.depositFor(deposit_user, deposit_amount) + C.print(f"User balance: {rembadger.balanceOf(deposit_user)/1e18} remBADGER") + + assert prev_balance + deposit_amount == rembadger.balance() + assert approx( + prev_getPricePerFullShare, rembadger.getPricePerFullShare(), 0.0001 + ) # There is a 2 wei increase in the second deposit for some reason (perhaps Brownie weirdness?) + assert approx( + rembadger.balanceOf(deposit_user), + (deposit_amount * 1e18) / prev_getPricePerFullShare, + 0.1, + ) # Governance bricks deposit to restore final state rembadger.brickDeposits() @@ -117,24 +120,17 @@ def main(queue="true", simulation="false"): ### === Final Simulation === ### if simulation == "true": - chain.snapshot() - # User withdraws and recovers its original BADGER (no more since emissions ended) - prev_balance = badger.balanceOf(DEPOSIT_USER) - rembadger.withdrawAll({"from": user}) - after_balance = badger.balanceOf(DEPOSIT_USER) - withdrawn = after_balance - prev_balance - assert approx(withdrawn, DEPOSIT_AMOUNT, 0.1) - C.print(f"User balance withdrawn: {withdrawn/1e18} BADGER") - chain.revert() + for deposit_user, deposit_amount in USERS_AMOUNTS.items(): + chain.snapshot() + # User withdraws and recovers its original BADGER (no more since emissions ended) + user = accounts.at(deposit_user, force=True) + prev_balance = badger.balanceOf(deposit_user) + rembadger.withdrawAll({"from": user}) + after_balance = badger.balanceOf(deposit_user) + withdrawn = after_balance - prev_balance + assert approx(withdrawn, deposit_amount, 0.1) + C.print(f"User balance withdrawn: {withdrawn/1e18} BADGER") + chain.revert() if simulation == "false": safe.post_safe_tx() - - -def approx(actual, expected, percentage_threshold): - print(actual, expected, percentage_threshold) - diff = int(abs(actual - expected)) - # 0 diff should automtically be a match - if diff == 0: - return True - return diff < (actual * percentage_threshold // 100)