diff --git a/packages/contracts/src/dollar/utils/BondingDebt.sol b/packages/contracts/src/dollar/utils/BondingDebt.sol new file mode 100644 index 000000000..b10e6550b --- /dev/null +++ b/packages/contracts/src/dollar/utils/BondingDebt.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "../interfaces/IERC20Ubiquity.sol"; + +// Allows to claim UBQ missing compensation till 6th May 2024 for Bond holders affected with wrong staking multiplier +// Full explanation https://github.com/ubiquity/ubiquity-dollar/issues/752#issuecomment-2095837822 + +contract BondingDebt { + bool public isExecuted; + + function reward() external { + require(!isExecuted, "Already executed"); + + isExecuted = true; + + address governanceToken = 0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0; + address treasuryAddress = 0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd; + + // Bond 1 + IERC20Ubiquity(governanceToken).mint(0x89eae71B865A2A39cBa62060aB1b40bbFFaE5b0D, 35704952407232639376); + IERC20Ubiquity(governanceToken).mint(treasuryAddress, 7140990481446527875); + + // Bond 2 + IERC20Ubiquity(governanceToken).mint(0x4007CE2083c7F3E18097aeB3A39bb8eC149a341d, 2630501621780289065714618); + IERC20Ubiquity(governanceToken).mint(treasuryAddress, 526100324356057813142923); + + // Bond 3 + IERC20Ubiquity(governanceToken).mint(0x7c76f4DB70b7E2177de10DE3e2f668daDcd11108, 1577484595484460523315806); + IERC20Ubiquity(governanceToken).mint(treasuryAddress, 315496919096892104663161); + + // Bond 4 (already expired 2 week bond hence we skip it for simplicity) + + // Bond 5 + IERC20Ubiquity(governanceToken).mint(0xa53A6fE2d8Ad977aD926C485343Ba39f32D3A3F6, 329713782662103366904643); + IERC20Ubiquity(governanceToken).mint(treasuryAddress, 65942756532420673380928); + + // Bond 6 + IERC20Ubiquity(governanceToken).mint(0xCEFD0E73cC48B0b9d4C8683E52B7d7396600AbB2, 317041833739125580390236); + IERC20Ubiquity(governanceToken).mint(treasuryAddress, 63408366747825116078047); + } +} \ No newline at end of file diff --git a/packages/contracts/test/dollar/utils/BondingDebt.t.sol b/packages/contracts/test/dollar/utils/BondingDebt.t.sol new file mode 100644 index 000000000..36912b3b2 --- /dev/null +++ b/packages/contracts/test/dollar/utils/BondingDebt.t.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "forge-std/Test.sol"; +import {UbiquityAlgorithmicDollarManager} from "../../../src/deprecated/UbiquityAlgorithmicDollarManager.sol"; +import {IERC20Ubiquity} from "../../../src/dollar/interfaces/IERC20Ubiquity.sol"; +import {BondingDebt} from "../../../src/dollar/utils/BondingDebt.sol"; + +contract BondingDebtTest is Test { + BondingDebt bondingDebt; + UbiquityAlgorithmicDollarManager dollarManager = UbiquityAlgorithmicDollarManager(0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98); + IERC20Ubiquity governanceToken = IERC20Ubiquity(0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0); + + address ubqEth = 0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd; + address treasuryAddress = 0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd; + address anyUser = address(1); + + function setUp() public { + vm.createSelectFork("https://mainnet.gateway.tenderly.co"); + + bondingDebt = new BondingDebt(); + + // `ubq.eth` give "UBQ_MINTER_ROLE" to BondingDebt contract + vm.prank(ubqEth); + dollarManager.grantRole( + keccak256("UBQ_MINTER_ROLE"), + address(bondingDebt) + ); + + // 0x3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9 + console.logBytes32(keccak256("UBQ_MINTER_ROLE")); + } + + function testReward_ShouldDistributeRewards() public { + // balances before + uint userBalanceBond1 = governanceToken.balanceOf(0x89eae71B865A2A39cBa62060aB1b40bbFFaE5b0D); + uint userBalanceBond2 = governanceToken.balanceOf(0x4007CE2083c7F3E18097aeB3A39bb8eC149a341d); + uint userBalanceBond3 = governanceToken.balanceOf(0x7c76f4DB70b7E2177de10DE3e2f668daDcd11108); + uint userBalanceBond5 = governanceToken.balanceOf(0xa53A6fE2d8Ad977aD926C485343Ba39f32D3A3F6); + uint userBalanceBond6 = governanceToken.balanceOf(0xCEFD0E73cC48B0b9d4C8683E52B7d7396600AbB2); + uint treasuryBalance = governanceToken.balanceOf(treasuryAddress); + + vm.prank(anyUser); + bondingDebt.reward(); + + assertEq(governanceToken.balanceOf(0x89eae71B865A2A39cBa62060aB1b40bbFFaE5b0D), userBalanceBond1 + 35704952407232639376); + assertEq(governanceToken.balanceOf(0x4007CE2083c7F3E18097aeB3A39bb8eC149a341d), userBalanceBond2 + 2630501621780289065714618); + assertEq(governanceToken.balanceOf(0x7c76f4DB70b7E2177de10DE3e2f668daDcd11108), userBalanceBond3 + 1577484595484460523315806); + assertEq(governanceToken.balanceOf(0xa53A6fE2d8Ad977aD926C485343Ba39f32D3A3F6), userBalanceBond5 + 329713782662103366904643); + assertEq(governanceToken.balanceOf(0xCEFD0E73cC48B0b9d4C8683E52B7d7396600AbB2), userBalanceBond6 + 317041833739125580390236); + assertEq(governanceToken.balanceOf(treasuryAddress), treasuryBalance + 7140990481446527875 + 526100324356057813142923 + 315496919096892104663161 + 65942756532420673380928 + 63408366747825116078047); + } + + function testReward_ShouldNotDistributeTwice() public { + vm.prank(anyUser); + bondingDebt.reward(); + + vm.prank(anyUser); + vm.expectRevert("Already executed"); + bondingDebt.reward(); + } +}