main #1
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,3 +16,4 @@ docs/
|
|||||||
|
|
||||||
# yarn
|
# yarn
|
||||||
yarn-error*
|
yarn-error*
|
||||||
|
yarn.lock
|
@ -9,7 +9,7 @@ optimizer-runs = 10_000_000
|
|||||||
|
|
||||||
[fmt]
|
[fmt]
|
||||||
|
|
||||||
line_length = 140
|
line_length = 110
|
||||||
bracket_spacing = true
|
bracket_spacing = true
|
||||||
multiline_func_header = 'attributes_first'
|
multiline_func_header = 'attributes_first'
|
||||||
number_underscore = 'thousands'
|
number_underscore = 'thousands'
|
@ -6,7 +6,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "forge test -vvv --fork-url https://rpc.mevblocker.io --fork-block-number 17336117 --no-match-contract TestRelayerBalance --gas-report",
|
"test": "forge test -vvv --fork-url https://rpc.mevblocker.io --fork-block-number 17336117 --no-match-contract TestRelayerBalance --gas-report",
|
||||||
"relayerBalancesSum": "forge test -vvv --fork-url https://rpc.mevblocker.io --fork-block-number 17304425 --match-contract TestRelayerBalance --gas-report"
|
"relayerBalancesSum": "forge test -vvv --fork-url https://rpc.mevblocker.io --fork-block-number 17304722 --match-contract TestRelayerBalance --gas-report"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gnosis.pm/ido-contracts": "^0.5.0",
|
"@gnosis.pm/ido-contracts": "^0.5.0",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
@proprietary/=src/proprietary/
|
@proprietary/=test/proprietary/
|
||||||
@interfaces/=src/interfaces/
|
@interfaces/=test/interfaces/
|
||||||
@root/=src/
|
@root/=src/
|
||||||
@forge-std/=lib/forge-std/src/
|
@forge-std/=lib/forge-std/src/
|
||||||
|
|
||||||
|
@ -13,7 +13,10 @@ abstract contract Delegation is Core {
|
|||||||
|
|
||||||
function delegate(address to) external {
|
function delegate(address to) external {
|
||||||
address previous = delegatedTo[msg.sender];
|
address previous = delegatedTo[msg.sender];
|
||||||
require(to != msg.sender && to != address(this) && to != address(0) && to != previous, "Governance: invalid delegatee");
|
require(
|
||||||
|
to != msg.sender && to != address(this) && to != address(0) && to != previous,
|
||||||
|
"Governance: invalid delegatee"
|
||||||
|
);
|
||||||
if (previous != address(0)) {
|
if (previous != address(0)) {
|
||||||
emit Undelegated(msg.sender, previous);
|
emit Undelegated(msg.sender, previous);
|
||||||
}
|
}
|
||||||
@ -29,12 +32,18 @@ abstract contract Delegation is Core {
|
|||||||
emit Undelegated(msg.sender, previous);
|
emit Undelegated(msg.sender, previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
function proposeByDelegate(address from, address target, string memory description) external returns (uint256) {
|
function proposeByDelegate(address from, address target, string memory description)
|
||||||
|
external
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
require(delegatedTo[from] == msg.sender, "Governance: not authorized");
|
require(delegatedTo[from] == msg.sender, "Governance: not authorized");
|
||||||
return _propose(from, target, description);
|
return _propose(from, target, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _propose(address proposer, address target, string memory description) internal virtual returns (uint256);
|
function _propose(address proposer, address target, string memory description)
|
||||||
|
internal
|
||||||
|
virtual
|
||||||
|
returns (uint256);
|
||||||
|
|
||||||
function castDelegatedVote(address[] memory from, uint256 proposalId, bool support) external virtual {
|
function castDelegatedVote(address[] memory from, uint256 proposalId, bool support) external virtual {
|
||||||
for (uint256 i = 0; i < from.length; i++) {
|
for (uint256 i = 0; i < from.length; i++) {
|
||||||
|
@ -68,7 +68,12 @@ contract Governance is Initializable, Configuration, Delegation, EnsResolve {
|
|||||||
|
|
||||||
/// @notice An event emitted when a new proposal is created
|
/// @notice An event emitted when a new proposal is created
|
||||||
event ProposalCreated(
|
event ProposalCreated(
|
||||||
uint256 indexed id, address indexed proposer, address target, uint256 startTime, uint256 endTime, string description
|
uint256 indexed id,
|
||||||
|
address indexed proposer,
|
||||||
|
address target,
|
||||||
|
uint256 startTime,
|
||||||
|
uint256 endTime,
|
||||||
|
string description
|
||||||
);
|
);
|
||||||
|
|
||||||
/// @notice An event emitted when a vote has been cast on a proposal
|
/// @notice An event emitted when a vote has been cast on a proposal
|
||||||
@ -102,7 +107,10 @@ contract Governance is Initializable, Configuration, Delegation, EnsResolve {
|
|||||||
_initializeConfiguration();
|
_initializeConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
function lock(address owner, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual {
|
function lock(address owner, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
|
||||||
|
public
|
||||||
|
virtual
|
||||||
|
{
|
||||||
torn.permit(owner, address(this), amount, deadline, v, r, s);
|
torn.permit(owner, address(this), amount, deadline, v, r, s);
|
||||||
_transferTokens(owner, amount);
|
_transferTokens(owner, amount);
|
||||||
}
|
}
|
||||||
@ -135,7 +143,9 @@ contract Governance is Initializable, Configuration, Delegation, EnsResolve {
|
|||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
uint256 votingPower = lockedBalance[proposer];
|
uint256 votingPower = lockedBalance[proposer];
|
||||||
require(votingPower >= PROPOSAL_THRESHOLD, "Governance::propose: proposer votes below proposal threshold");
|
require(
|
||||||
|
votingPower >= PROPOSAL_THRESHOLD, "Governance::propose: proposer votes below proposal threshold"
|
||||||
|
);
|
||||||
// target should be a contract
|
// target should be a contract
|
||||||
require(Address.isContract(target), "Governance::propose: not a contract");
|
require(Address.isContract(target), "Governance::propose: not a contract");
|
||||||
|
|
||||||
@ -143,7 +153,8 @@ contract Governance is Initializable, Configuration, Delegation, EnsResolve {
|
|||||||
if (latestProposalId != 0) {
|
if (latestProposalId != 0) {
|
||||||
ProposalState proposersLatestProposalState = state(latestProposalId);
|
ProposalState proposersLatestProposalState = state(latestProposalId);
|
||||||
require(
|
require(
|
||||||
proposersLatestProposalState != ProposalState.Active && proposersLatestProposalState != ProposalState.Pending,
|
proposersLatestProposalState != ProposalState.Active
|
||||||
|
&& proposersLatestProposalState != ProposalState.Pending,
|
||||||
"Governance::propose: one live proposal per proposer, found an already active proposal"
|
"Governance::propose: one live proposal per proposer, found an already active proposal"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -172,7 +183,10 @@ contract Governance is Initializable, Configuration, Delegation, EnsResolve {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function execute(uint256 proposalId) public payable virtual {
|
function execute(uint256 proposalId) public payable virtual {
|
||||||
require(state(proposalId) == ProposalState.AwaitingExecution, "Governance::execute: invalid proposal state");
|
require(
|
||||||
|
state(proposalId) == ProposalState.AwaitingExecution,
|
||||||
|
"Governance::execute: invalid proposal state"
|
||||||
|
);
|
||||||
Proposal storage proposal = proposals[proposalId];
|
Proposal storage proposal = proposals[proposalId];
|
||||||
proposal.executed = true;
|
proposal.executed = true;
|
||||||
|
|
||||||
@ -226,7 +240,9 @@ contract Governance is Initializable, Configuration, Delegation, EnsResolve {
|
|||||||
receipt.hasVoted = true;
|
receipt.hasVoted = true;
|
||||||
receipt.support = support;
|
receipt.support = support;
|
||||||
receipt.votes = votes;
|
receipt.votes = votes;
|
||||||
_lockTokens(voter, proposal.endTime.add(VOTE_EXTEND_TIME).add(EXECUTION_EXPIRATION).add(EXECUTION_DELAY));
|
_lockTokens(
|
||||||
|
voter, proposal.endTime.add(VOTE_EXTEND_TIME).add(EXECUTION_EXPIRATION).add(EXECUTION_DELAY)
|
||||||
|
);
|
||||||
emit Voted(proposalId, voter, support, votes);
|
emit Voted(proposalId, voter, support, votes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +268,10 @@ contract Governance is Initializable, Configuration, Delegation, EnsResolve {
|
|||||||
return ProposalState.Pending;
|
return ProposalState.Pending;
|
||||||
} else if (getBlockTimestamp() <= proposal.endTime) {
|
} else if (getBlockTimestamp() <= proposal.endTime) {
|
||||||
return ProposalState.Active;
|
return ProposalState.Active;
|
||||||
} else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes + proposal.againstVotes < QUORUM_VOTES) {
|
} else if (
|
||||||
|
proposal.forVotes <= proposal.againstVotes
|
||||||
|
|| proposal.forVotes + proposal.againstVotes < QUORUM_VOTES
|
||||||
|
) {
|
||||||
return ProposalState.Defeated;
|
return ProposalState.Defeated;
|
||||||
} else if (proposal.executed) {
|
} else if (proposal.executed) {
|
||||||
return ProposalState.Executed;
|
return ProposalState.Executed;
|
||||||
|
@ -13,7 +13,11 @@ contract LoopbackProxy is TransparentUpgradeableProxy, EnsResolve {
|
|||||||
/**
|
/**
|
||||||
* @dev Initializes an upgradeable proxy backed by the implementation at `_logic`.
|
* @dev Initializes an upgradeable proxy backed by the implementation at `_logic`.
|
||||||
*/
|
*/
|
||||||
constructor(address _logic, bytes memory _data) public payable TransparentUpgradeableProxy(_logic, address(this), _data) { }
|
constructor(address _logic, bytes memory _data)
|
||||||
|
public
|
||||||
|
payable
|
||||||
|
TransparentUpgradeableProxy(_logic, address(this), _data)
|
||||||
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Override to allow admin (itself) access the fallback function.
|
* @dev Override to allow admin (itself) access the fallback function.
|
||||||
|
@ -1,13 +1 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
pragma solidity ^0.6.0;
|
|
||||||
|
|
||||||
import "../LoopbackProxy.sol";
|
|
||||||
|
|
||||||
contract MockProxy is LoopbackProxy {
|
|
||||||
constructor(address _logic, bytes memory _data) public payable LoopbackProxy(_logic, _data) { }
|
|
||||||
|
|
||||||
function resolve(bytes32 addr) public view override returns (address) {
|
|
||||||
return address(uint160(uint256(addr) >> (12 * 8)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,31 +1 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
pragma solidity ^0.6.0;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "torn-token/contracts/mocks/TORNMock.sol";
|
|
||||||
|
|
||||||
struct Recipient2 {
|
|
||||||
address to;
|
|
||||||
uint256 amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
contract TORNMock2 is TORNMock {
|
|
||||||
constructor(address _governance, uint256 _pausePeriod, Recipient2[] memory vesting)
|
|
||||||
public
|
|
||||||
TORNMock(solve(_governance), _pausePeriod, solve2(vesting))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
function solve(address x) private returns (bytes32) {
|
|
||||||
return bytes32(uint256(x) << 96);
|
|
||||||
}
|
|
||||||
|
|
||||||
function solve2(Recipient2[] memory vesting) private returns (Recipient[] memory) {
|
|
||||||
Recipient[] memory realVesting = new Recipient[](vesting.length);
|
|
||||||
for (uint256 i = 0; i < vesting.length; i++) {
|
|
||||||
realVesting[i].to = solve(vesting[i].to);
|
|
||||||
realVesting[i].amount = vesting[i].amount;
|
|
||||||
}
|
|
||||||
return realVesting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -19,7 +19,11 @@ contract GovernanceGasUpgrade is GovernanceVaultUpgrade, GasCompensator {
|
|||||||
* @param _userVault tornado vault address
|
* @param _userVault tornado vault address
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constructor(address _gasCompLogic, address _userVault) public GovernanceVaultUpgrade(_userVault) GasCompensator(_gasCompLogic) { }
|
constructor(address _gasCompLogic, address _userVault)
|
||||||
|
public
|
||||||
|
GovernanceVaultUpgrade(_userVault)
|
||||||
|
GasCompensator(_gasCompLogic)
|
||||||
|
{ }
|
||||||
|
|
||||||
/// @notice check that msg.sender is multisig
|
/// @notice check that msg.sender is multisig
|
||||||
modifier onlyMultisig() {
|
modifier onlyMultisig() {
|
||||||
@ -40,7 +44,11 @@ contract GovernanceGasUpgrade is GovernanceVaultUpgrade, GasCompensator {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function setGasCompensations(uint256 gasCompensationsLimit) external virtual override onlyMultisig {
|
function setGasCompensations(uint256 gasCompensationsLimit) external virtual override onlyMultisig {
|
||||||
require(payable(address(gasCompensationVault)).send(Math.min(gasCompensationsLimit, address(this).balance)));
|
require(
|
||||||
|
payable(address(gasCompensationVault)).send(
|
||||||
|
Math.min(gasCompensationsLimit, address(this).balance)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,9 +93,18 @@ contract GovernanceGasUpgrade is GovernanceVaultUpgrade, GasCompensator {
|
|||||||
* @param support true if yes false if no
|
* @param support true if yes false if no
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function castDelegatedVote(address[] memory from, uint256 proposalId, bool support) external virtual override {
|
function castDelegatedVote(address[] memory from, uint256 proposalId, bool support)
|
||||||
|
external
|
||||||
|
virtual
|
||||||
|
override
|
||||||
|
{
|
||||||
require(from.length > 0, "Can not be empty");
|
require(from.length > 0, "Can not be empty");
|
||||||
_castDelegatedVote(from, proposalId, support, !hasAccountVoted(proposalId, msg.sender) && !checkIfQuorumReached(proposalId));
|
_castDelegatedVote(
|
||||||
|
from,
|
||||||
|
proposalId,
|
||||||
|
support,
|
||||||
|
!hasAccountVoted(proposalId, msg.sender) && !checkIfQuorumReached(proposalId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice checker for success on deployment
|
/// @notice checker for success on deployment
|
||||||
@ -148,7 +165,9 @@ contract GovernanceGasUpgrade is GovernanceVaultUpgrade, GasCompensator {
|
|||||||
{
|
{
|
||||||
for (uint256 i = 0; i < from.length; i++) {
|
for (uint256 i = 0; i < from.length; i++) {
|
||||||
address delegator = from[i];
|
address delegator = from[i];
|
||||||
require(delegatedTo[delegator] == msg.sender || delegator == msg.sender, "Governance: not authorized");
|
require(
|
||||||
|
delegatedTo[delegator] == msg.sender || delegator == msg.sender, "Governance: not authorized"
|
||||||
|
);
|
||||||
require(!gasCompensated || !hasAccountVoted(proposalId, delegator), "Governance: voted already");
|
require(!gasCompensated || !hasAccountVoted(proposalId, delegator), "Governance: voted already");
|
||||||
_castVote(delegator, proposalId, support);
|
_castVote(delegator, proposalId, support);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
pragma solidity ^0.6.12;
|
|
||||||
|
|
||||||
import "../../v1/Governance.sol";
|
|
||||||
|
|
||||||
contract MockProposal {
|
|
||||||
address public constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
|
||||||
|
|
||||||
function executeProposal() external {
|
|
||||||
Governance gov = Governance(GovernanceAddress);
|
|
||||||
|
|
||||||
gov.setVotingPeriod(27_000);
|
|
||||||
require(gov.VOTING_PERIOD() == 27_000, "Voting period change failed!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -11,7 +11,11 @@ contract AdminUpgradeableProxy is TransparentUpgradeableProxy {
|
|||||||
/**
|
/**
|
||||||
* @dev Initializes an upgradeable proxy backed by the implementation at `_logic`.
|
* @dev Initializes an upgradeable proxy backed by the implementation at `_logic`.
|
||||||
*/
|
*/
|
||||||
constructor(address _logic, address _admin, bytes memory _data) public payable TransparentUpgradeableProxy(_logic, _admin, _data) { }
|
constructor(address _logic, address _admin, bytes memory _data)
|
||||||
|
public
|
||||||
|
payable
|
||||||
|
TransparentUpgradeableProxy(_logic, _admin, _data)
|
||||||
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Override to allow admin access the fallback function.
|
* @dev Override to allow admin access the fallback function.
|
||||||
|
@ -37,7 +37,10 @@ contract GovernancePatchUpgrade is GovernanceStakingUpgrade {
|
|||||||
proposalCodehash := extcodehash(target)
|
proposalCodehash := extcodehash(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
require(proposalCodehash == proposalCodehashes[proposalId], "Governance::propose: metamorphic contracts not allowed");
|
require(
|
||||||
|
proposalCodehash == proposalCodehashes[proposalId],
|
||||||
|
"Governance::propose: metamorphic contracts not allowed"
|
||||||
|
);
|
||||||
|
|
||||||
super.execute(proposalId);
|
super.execute(proposalId);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,10 @@ contract PatchProposalContractsFactory {
|
|||||||
* @param registry The address of the relayer registry.
|
* @param registry The address of the relayer registry.
|
||||||
* @return The address of the new staking contract.
|
* @return The address of the new staking contract.
|
||||||
*/
|
*/
|
||||||
function createStakingRewards(address governance, address torn, address registry) external returns (address) {
|
function createStakingRewards(address governance, address torn, address registry)
|
||||||
|
external
|
||||||
|
returns (address)
|
||||||
|
{
|
||||||
return address(new TornadoStakingRewards(governance, torn, registry));
|
return address(new TornadoStakingRewards(governance, torn, registry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,10 +39,13 @@ contract PatchProposalContractsFactory {
|
|||||||
* @param staking The TornadoStakingRewards contract address.
|
* @param staking The TornadoStakingRewards contract address.
|
||||||
* @return The address of the new registry contract.
|
* @return The address of the new registry contract.
|
||||||
*/
|
*/
|
||||||
function createRegistryContract(address torn, address governance, address ens, address staking, address feeManager)
|
function createRegistryContract(
|
||||||
external
|
address torn,
|
||||||
returns (address)
|
address governance,
|
||||||
{
|
address ens,
|
||||||
|
address staking,
|
||||||
|
address feeManager
|
||||||
|
) external returns (address) {
|
||||||
return address(new RelayerRegistry(torn, governance, ens, staking, feeManager));
|
return address(new RelayerRegistry(torn, governance, ens, staking, feeManager));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,9 +57,9 @@ contract PatchProposal {
|
|||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
using Address for address;
|
using Address for address;
|
||||||
|
|
||||||
address public immutable feeManagerAddress = 0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7;
|
address public immutable feeManagerProxyAddress = 0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7;
|
||||||
|
address public immutable registryProxyAddress = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
||||||
address public immutable ensAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
|
address public immutable ensAddress = 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
|
||||||
address public immutable registry = 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
|
||||||
|
|
||||||
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
|
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
|
||||||
|
|
||||||
@ -73,31 +79,39 @@ contract PatchProposal {
|
|||||||
address vault = address(GovernancePatchUpgrade(governance).userVault());
|
address vault = address(GovernancePatchUpgrade(governance).userVault());
|
||||||
|
|
||||||
// Get the old staking contract
|
// Get the old staking contract
|
||||||
TornadoStakingRewards oldStaking = TornadoStakingRewards(address(GovernancePatchUpgrade(governance).Staking()));
|
TornadoStakingRewards oldStaking =
|
||||||
|
TornadoStakingRewards(address(GovernancePatchUpgrade(governance).Staking()));
|
||||||
|
|
||||||
// Get the small amount of TORN left
|
// Get the small amount of TORN left
|
||||||
oldStaking.withdrawTorn(TORN.balanceOf(address(oldStaking)));
|
oldStaking.withdrawTorn(TORN.balanceOf(address(oldStaking)));
|
||||||
|
|
||||||
// And create a new staking logic contract
|
// And create a new staking logic contract
|
||||||
TornadoStakingRewards newStakingImplementation =
|
TornadoStakingRewards newStakingImplementation = TornadoStakingRewards(
|
||||||
TornadoStakingRewards(patchProposalContractsFactory.createStakingRewards(address(governance), address(TORN), registry));
|
patchProposalContractsFactory.createStakingRewards(
|
||||||
|
address(governance), address(TORN), registryProxyAddress
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// Create new staking proxy contract (without initialization value)
|
// Create new staking proxy contract (without initialization value)
|
||||||
bytes memory empty;
|
bytes memory empty;
|
||||||
AdminUpgradeableProxy newStaking = new AdminUpgradeableProxy(address(newStakingImplementation), address(governance), empty);
|
|
||||||
|
address newStaking =
|
||||||
|
address(new AdminUpgradeableProxy(address(newStakingImplementation), address(governance), empty));
|
||||||
|
|
||||||
// And a new registry implementation
|
// And a new registry implementation
|
||||||
address newRegistryImplementationAddress = patchProposalContractsFactory.createRegistryContract(
|
address newRegistryImplementationAddress = patchProposalContractsFactory.createRegistryContract(
|
||||||
address(TORN), address(governance), ensAddress, address(newStaking), feeManagerAddress
|
address(TORN), address(governance), ensAddress, newStaking, feeManagerProxyAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
// Upgrade the registry proxy
|
// Upgrade the registry proxy
|
||||||
AdminUpgradeableProxy(payable(registry)).upgradeTo(newRegistryImplementationAddress);
|
AdminUpgradeableProxy(payable(registryProxyAddress)).upgradeTo(newRegistryImplementationAddress);
|
||||||
|
|
||||||
// Now upgrade the governance to the latest stuff
|
// Now upgrade the governance to the latest stuff
|
||||||
LoopbackProxy(payable(governance)).upgradeTo(address(new GovernancePatchUpgrade(address(newStaking), gasComp, vault)));
|
LoopbackProxy(payable(governance)).upgradeTo(
|
||||||
|
address(new GovernancePatchUpgrade(newStaking, gasComp, vault))
|
||||||
|
);
|
||||||
|
|
||||||
// Return TORNs, which were withdrawn by bug, to Governance Staking contract
|
// Compensate TORN for staking
|
||||||
TORN.transfer(address(newStaking), 94_092 ether);
|
TORN.transfer(newStaking, 94_092 ether);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,9 @@ contract RelayerRegistry is Initializable, EnsResolve {
|
|||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(address _torn, address _governance, address _ens, address _staking, address _feeManager) public {
|
constructor(address _torn, address _governance, address _ens, address _staking, address _feeManager)
|
||||||
|
public
|
||||||
|
{
|
||||||
torn = TORN(_torn);
|
torn = TORN(_torn);
|
||||||
governance = _governance;
|
governance = _governance;
|
||||||
ens = IENS(_ens);
|
ens = IENS(_ens);
|
||||||
@ -157,7 +159,9 @@ contract RelayerRegistry is Initializable, EnsResolve {
|
|||||||
* @param stake the initial amount of stake in TORN the relayer is depositing
|
* @param stake the initial amount of stake in TORN the relayer is depositing
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function register(string calldata ensName, uint256 stake, address[] calldata workersToRegister) external {
|
function register(string calldata ensName, uint256 stake, address[] calldata workersToRegister)
|
||||||
|
external
|
||||||
|
{
|
||||||
_register(msg.sender, ensName, stake, workersToRegister);
|
_register(msg.sender, ensName, stake, workersToRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +183,12 @@ contract RelayerRegistry is Initializable, EnsResolve {
|
|||||||
_register(relayer, ensName, stake, workersToRegister);
|
_register(relayer, ensName, stake, workersToRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _register(address relayer, string calldata ensName, uint256 stake, address[] calldata workersToRegister) internal {
|
function _register(
|
||||||
|
address relayer,
|
||||||
|
string calldata ensName,
|
||||||
|
uint256 stake,
|
||||||
|
address[] calldata workersToRegister
|
||||||
|
) internal {
|
||||||
bytes32 ensHash = bytes(ensName).namehash();
|
bytes32 ensHash = bytes(ensName).namehash();
|
||||||
require(relayer == ens.owner(ensHash), "only ens owner");
|
require(relayer == ens.owner(ensHash), "only ens owner");
|
||||||
require(workers[relayer] == address(0), "cant register again");
|
require(workers[relayer] == address(0), "cant register again");
|
||||||
@ -249,9 +258,15 @@ contract RelayerRegistry is Initializable, EnsResolve {
|
|||||||
* @param staker address from that stake is paid
|
* @param staker address from that stake is paid
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function stakeToRelayerPermit(address relayer, uint256 stake, address staker, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
|
function stakeToRelayerPermit(
|
||||||
external
|
address relayer,
|
||||||
{
|
uint256 stake,
|
||||||
|
address staker,
|
||||||
|
uint256 deadline,
|
||||||
|
uint8 v,
|
||||||
|
bytes32 r,
|
||||||
|
bytes32 s
|
||||||
|
) external {
|
||||||
torn.permit(staker, address(this), stake, deadline, v, r, s);
|
torn.permit(staker, address(this), stake, deadline, v, r, s);
|
||||||
_stakeToRelayer(staker, relayer, stake);
|
_stakeToRelayer(staker, relayer, stake);
|
||||||
}
|
}
|
||||||
|
@ -85,8 +85,9 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
|
|||||||
*/
|
*/
|
||||||
function addBurnRewards(uint256 amount) external {
|
function addBurnRewards(uint256 amount) external {
|
||||||
require(msg.sender == address(Governance) || msg.sender == relayerRegistry, "unauthorized");
|
require(msg.sender == address(Governance) || msg.sender == relayerRegistry, "unauthorized");
|
||||||
accumulatedRewardPerTorn =
|
accumulatedRewardPerTorn = accumulatedRewardPerTorn.add(
|
||||||
accumulatedRewardPerTorn.add(amount.mul(ratioConstant).div(torn.balanceOf(address(Governance.userVault()))));
|
amount.mul(ratioConstant).div(torn.balanceOf(address(Governance.userVault())))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +96,10 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
|
|||||||
* @param amountLockedBeforehand the balance locked beforehand in the governance contract
|
* @param amountLockedBeforehand the balance locked beforehand in the governance contract
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function updateRewardsOnLockedBalanceChange(address account, uint256 amountLockedBeforehand) external onlyGovernance {
|
function updateRewardsOnLockedBalanceChange(address account, uint256 amountLockedBeforehand)
|
||||||
|
external
|
||||||
|
onlyGovernance
|
||||||
|
{
|
||||||
uint256 claimed = _updateReward(account, amountLockedBeforehand);
|
uint256 claimed = _updateReward(account, amountLockedBeforehand);
|
||||||
accumulatedRewards[account] = accumulatedRewards[account].add(claimed);
|
accumulatedRewards[account] = accumulatedRewards[account].add(claimed);
|
||||||
}
|
}
|
||||||
@ -119,10 +123,14 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
|
|||||||
* @param amountLockedBeforehand the balance locked beforehand in the governance contract
|
* @param amountLockedBeforehand the balance locked beforehand in the governance contract
|
||||||
* @return claimed the rewards attributed to user since the last update
|
* @return claimed the rewards attributed to user since the last update
|
||||||
*/
|
*/
|
||||||
function _updateReward(address account, uint256 amountLockedBeforehand) private returns (uint256 claimed) {
|
function _updateReward(address account, uint256 amountLockedBeforehand)
|
||||||
|
private
|
||||||
|
returns (uint256 claimed)
|
||||||
|
{
|
||||||
if (amountLockedBeforehand != 0) {
|
if (amountLockedBeforehand != 0) {
|
||||||
claimed =
|
claimed = (accumulatedRewardPerTorn.sub(accumulatedRewardRateOnLastUpdate[account])).mul(
|
||||||
(accumulatedRewardPerTorn.sub(accumulatedRewardRateOnLastUpdate[account])).mul(amountLockedBeforehand).div(ratioConstant);
|
amountLockedBeforehand
|
||||||
|
).div(ratioConstant);
|
||||||
}
|
}
|
||||||
accumulatedRewardRateOnLastUpdate[account] = accumulatedRewardPerTorn;
|
accumulatedRewardRateOnLastUpdate[account] = accumulatedRewardPerTorn;
|
||||||
emit RewardsUpdated(account, claimed);
|
emit RewardsUpdated(account, claimed);
|
||||||
@ -135,7 +143,9 @@ contract TornadoStakingRewards is Initializable, EnsResolve {
|
|||||||
function checkReward(address account) external view returns (uint256 rewards) {
|
function checkReward(address account) external view returns (uint256 rewards) {
|
||||||
uint256 amountLocked = Governance.lockedBalance(account);
|
uint256 amountLocked = Governance.lockedBalance(account);
|
||||||
if (amountLocked != 0) {
|
if (amountLocked != 0) {
|
||||||
rewards = (accumulatedRewardPerTorn.sub(accumulatedRewardRateOnLastUpdate[account])).mul(amountLocked).div(ratioConstant);
|
rewards = (accumulatedRewardPerTorn.sub(accumulatedRewardRateOnLastUpdate[account])).mul(
|
||||||
|
amountLocked
|
||||||
|
).div(ratioConstant);
|
||||||
}
|
}
|
||||||
rewards = rewards.add(accumulatedRewards[account]);
|
rewards = rewards.add(accumulatedRewards[account]);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
pragma solidity 0.6.12;
|
pragma solidity 0.6.12;
|
||||||
|
|
||||||
interface IMetamorphicContractFactory {
|
interface IMetamorphicContractFactory {
|
||||||
function findMetamorphicContractAddress(bytes32 salt) external view returns (address metamorphicContractAddress);
|
function findMetamorphicContractAddress(bytes32 salt)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (address metamorphicContractAddress);
|
||||||
|
|
||||||
function deployMetamorphicContractFromExistingImplementation(
|
function deployMetamorphicContractFromExistingImplementation(
|
||||||
bytes32 salt,
|
bytes32 salt,
|
||||||
|
@ -1,40 +1,42 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
contract Mock {
|
contract Mock {
|
||||||
// Developer address with 22 staked TORN
|
// Developer address with 22 staked TORN
|
||||||
address public constant TEST_REAL_ADDRESS_WITH_BALANCE = 0x9Ff3C1Bea9ffB56a78824FE29f457F066257DD58;
|
address public constant TEST_REAL_ADDRESS_WITH_BALANCE = 0x9Ff3C1Bea9ffB56a78824FE29f457F066257DD58;
|
||||||
address public constant TEST_RELAYER_ADDRESS = 0x30F96AEF199B399B722F8819c9b0723016CEAe6C; // moon-relayer.eth (just for testing)
|
address public constant TEST_RELAYER_ADDRESS = 0x30F96AEF199B399B722F8819c9b0723016CEAe6C; // moon-relayer.eth (just for testing)
|
||||||
|
|
||||||
uint256 public constant TEST_PRIVATE_KEY_ONE = 0x66ddbd7cbe4a566df405f6ded0b908c669f88cdb1656380c050e3a457bd21df0;
|
uint256 public constant TEST_PRIVATE_KEY_ONE =
|
||||||
uint256 public constant TEST_PRIVATE_KEY_TWO = 0xa4c8c98120e77741a87a116074a2df4ddb20d1149069290fd4a3d7ee65c55064;
|
0x66ddbd7cbe4a566df405f6ded0b908c669f88cdb1656380c050e3a457bd21df0;
|
||||||
address public constant TEST_ADDRESS_ONE = 0x118251976c65AFAf291f5255450ddb5b6A4d8B88;
|
uint256 public constant TEST_PRIVATE_KEY_TWO =
|
||||||
address public constant TEST_ADDRESS_TWO = 0x63aE7d90Eb37ca39FC62dD9991DbEfeE70673a20;
|
0xa4c8c98120e77741a87a116074a2df4ddb20d1149069290fd4a3d7ee65c55064;
|
||||||
|
address public constant TEST_ADDRESS_ONE = 0x118251976c65AFAf291f5255450ddb5b6A4d8B88;
|
||||||
uint256 public constant ATTACKER_PROPOSAL_ID = 21; // Last attacker proposal (to restore Governance Vault balance) id
|
address public constant TEST_ADDRESS_TWO = 0x63aE7d90Eb37ca39FC62dD9991DbEfeE70673a20;
|
||||||
|
|
||||||
uint256 public constant PROPOSAL_VOTING_DURATION = 5 days;
|
uint256 public constant ATTACKER_PROPOSAL_ID = 21; // Last attacker proposal (to restore Governance Vault balance) id
|
||||||
uint256 public constant PROPOSAL_LOCKED_DURATION = 2 days;
|
|
||||||
uint256 public constant PROPOSAL_DURATION = PROPOSAL_VOTING_DURATION + PROPOSAL_LOCKED_DURATION;
|
uint256 public constant PROPOSAL_VOTING_DURATION = 5 days;
|
||||||
uint256 public constant PROPOSAL_EXECUTION_MAX_DURATION = 3 days;
|
uint256 public constant PROPOSAL_LOCKED_DURATION = 2 days;
|
||||||
uint256 public constant PROPOSAL_THRESHOLD = 25_000 ether;
|
uint256 public constant PROPOSAL_DURATION = PROPOSAL_VOTING_DURATION + PROPOSAL_LOCKED_DURATION;
|
||||||
string public constant PROPOSAL_DESCRIPTION = "{title:'Some proposal',description:''}";
|
uint256 public constant PROPOSAL_EXECUTION_MAX_DURATION = 3 days;
|
||||||
|
uint256 public constant PROPOSAL_THRESHOLD = 25_000 ether;
|
||||||
address public constant VERIFIER_ADDRESS = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
string public constant PROPOSAL_DESCRIPTION = "{title:'Some proposal',description:''}";
|
||||||
|
|
||||||
bytes32 public constant PERMIT_TYPEHASH =
|
address public constant VERIFIER_ADDRESS = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
||||||
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
|
|
||||||
|
bytes32 public constant PERMIT_TYPEHASH =
|
||||||
bytes32 public constant EIP712_DOMAIN = keccak256(
|
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
|
||||||
abi.encode(
|
|
||||||
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
|
bytes32 public constant EIP712_DOMAIN = keccak256(
|
||||||
keccak256(bytes("TornadoCash")),
|
abi.encode(
|
||||||
keccak256(bytes("1")),
|
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
|
||||||
1,
|
keccak256(bytes("TornadoCash")),
|
||||||
VERIFIER_ADDRESS
|
keccak256(bytes("1")),
|
||||||
)
|
1,
|
||||||
);
|
VERIFIER_ADDRESS
|
||||||
|
)
|
||||||
uint16 public constant PERMIT_FUNC_SELECTOR = uint16(0x1901);
|
);
|
||||||
}
|
|
||||||
|
uint16 public constant PERMIT_FUNC_SELECTOR = uint16(0x1901);
|
||||||
|
}
|
||||||
|
@ -1,89 +1,91 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import { Test } from "@forge-std/Test.sol";
|
import { Test } from "@forge-std/Test.sol";
|
||||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
import { ERC20Permit } from "torn-token/contracts/ERC20Permit.sol";
|
import { ERC20Permit } from "torn-token/contracts/ERC20Permit.sol";
|
||||||
import { console2 } from "@forge-std/console2.sol";
|
import { console2 } from "@forge-std/console2.sol";
|
||||||
|
|
||||||
import { Mock } from "./Mock.sol";
|
import { Mock } from "./Mock.sol";
|
||||||
import { Proposal, IGovernance } from "@interfaces/IGovernance.sol";
|
import { Proposal, IGovernance } from "@interfaces/IGovernance.sol";
|
||||||
import { Parameters } from "@proprietary/Parameters.sol";
|
import { Parameters } from "@proprietary/Parameters.sol";
|
||||||
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
|
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
|
||||||
|
|
||||||
contract ProposalUtils is Mock, Parameters, Test {
|
contract ProposalUtils is Mock, Parameters, Test {
|
||||||
GovernancePatchUpgrade internal governance = GovernancePatchUpgrade(payable(_governanceAddress));
|
GovernancePatchUpgrade internal governance = GovernancePatchUpgrade(payable(_governanceAddress));
|
||||||
|
|
||||||
function getProposalExecutableTime(uint256 proposalId) internal view returns (uint256) {
|
function getProposalExecutableTime(uint256 proposalId) internal view returns (uint256) {
|
||||||
Proposal memory proposal = IGovernance(_governanceAddress).proposals(proposalId);
|
Proposal memory proposal = IGovernance(_governanceAddress).proposals(proposalId);
|
||||||
return proposal.endTime + PROPOSAL_LOCKED_DURATION + 1 hours;
|
return proposal.endTime + PROPOSAL_LOCKED_DURATION + 1 hours;
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitUntilExecutable(uint256 proposalId) internal {
|
function waitUntilExecutable(uint256 proposalId) internal {
|
||||||
uint256 proposalExecutableTime = getProposalExecutableTime(proposalId);
|
uint256 proposalExecutableTime = getProposalExecutableTime(proposalId);
|
||||||
require(block.timestamp < proposalExecutableTime, "Too late to execute proposal");
|
require(block.timestamp < proposalExecutableTime, "Too late to execute proposal");
|
||||||
|
|
||||||
vm.warp(proposalExecutableTime);
|
vm.warp(proposalExecutableTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
function proposeAndVote(address proposalAddress) public returns (uint256) {
|
function proposeAndVote(address proposalAddress) public returns (uint256) {
|
||||||
retrieveAndLockBalance(TEST_PRIVATE_KEY_ONE, TEST_ADDRESS_ONE, PROPOSAL_THRESHOLD);
|
retrieveAndLockBalance(TEST_PRIVATE_KEY_ONE, TEST_ADDRESS_ONE, PROPOSAL_THRESHOLD);
|
||||||
retrieveAndLockBalance(TEST_PRIVATE_KEY_TWO, TEST_ADDRESS_TWO, 1 ether);
|
retrieveAndLockBalance(TEST_PRIVATE_KEY_TWO, TEST_ADDRESS_TWO, 1 ether);
|
||||||
|
|
||||||
/* ----------PROPOSER------------ */
|
/* ----------PROPOSER------------ */
|
||||||
vm.startPrank(TEST_ADDRESS_ONE);
|
vm.startPrank(TEST_ADDRESS_ONE);
|
||||||
|
|
||||||
uint256 proposalId = governance.propose(proposalAddress, PROPOSAL_DESCRIPTION);
|
uint256 proposalId = governance.propose(proposalAddress, PROPOSAL_DESCRIPTION);
|
||||||
|
|
||||||
// TIME-TRAVEL
|
// TIME-TRAVEL
|
||||||
vm.warp(block.timestamp + 6 hours);
|
vm.warp(block.timestamp + 6 hours);
|
||||||
|
|
||||||
governance.castVote(proposalId, true);
|
governance.castVote(proposalId, true);
|
||||||
|
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
/* ------------------------------ */
|
/* ------------------------------ */
|
||||||
|
|
||||||
/* -------------VOTER-------------*/
|
/* -------------VOTER-------------*/
|
||||||
vm.startPrank(TEST_ADDRESS_TWO);
|
vm.startPrank(TEST_ADDRESS_TWO);
|
||||||
governance.castVote(proposalId, true);
|
governance.castVote(proposalId, true);
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
/* ------------------------------ */
|
/* ------------------------------ */
|
||||||
|
|
||||||
return proposalId;
|
return proposalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function retrieveAndLockBalance(uint256 privateKey, address voter, uint256 amount) internal {
|
function retrieveAndLockBalance(uint256 privateKey, address voter, uint256 amount) internal {
|
||||||
uint256 lockTimestamp = block.timestamp + PROPOSAL_DURATION;
|
uint256 lockTimestamp = block.timestamp + PROPOSAL_DURATION;
|
||||||
uint256 accountNonce = ERC20Permit(_tokenAddress).nonces(voter);
|
uint256 accountNonce = ERC20Permit(_tokenAddress).nonces(voter);
|
||||||
|
|
||||||
bytes32 messageHash = keccak256(
|
console2.log("Account nonce: %s", accountNonce);
|
||||||
abi.encodePacked(
|
|
||||||
PERMIT_FUNC_SELECTOR,
|
bytes32 messageHash = keccak256(
|
||||||
EIP712_DOMAIN,
|
abi.encodePacked(
|
||||||
keccak256(abi.encode(PERMIT_TYPEHASH, voter, _governanceAddress, amount, accountNonce, lockTimestamp))
|
PERMIT_FUNC_SELECTOR,
|
||||||
)
|
EIP712_DOMAIN,
|
||||||
);
|
keccak256(abi.encode(PERMIT_TYPEHASH, voter, _governanceAddress, amount, accountNonce, lockTimestamp))
|
||||||
|
)
|
||||||
/* ----------GOVERNANCE------- */
|
);
|
||||||
vm.startPrank(_governanceAddress);
|
|
||||||
IERC20(_tokenAddress).transfer(voter, amount);
|
/* ----------GOVERNANCE------- */
|
||||||
vm.stopPrank();
|
vm.startPrank(_governanceAddress);
|
||||||
/* ----------------------------*/
|
IERC20(_tokenAddress).transfer(voter, amount);
|
||||||
|
vm.stopPrank();
|
||||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, messageHash);
|
/* ----------------------------*/
|
||||||
|
|
||||||
/* ----------VOTER------------ */
|
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, messageHash);
|
||||||
vm.startPrank(voter);
|
|
||||||
governance.lock(voter, amount, lockTimestamp, v, r, s);
|
/* ----------VOTER------------ */
|
||||||
vm.stopPrank();
|
vm.startPrank(voter);
|
||||||
/* ----------------------------*/
|
governance.lock(voter, amount, lockTimestamp, v, r, s);
|
||||||
}
|
vm.stopPrank();
|
||||||
|
/* ----------------------------*/
|
||||||
function proposeAndExecute(address proposalAddress) public {
|
}
|
||||||
uint256 proposalId = proposeAndVote(proposalAddress);
|
|
||||||
|
function proposeAndExecute(address proposalAddress) public {
|
||||||
waitUntilExecutable(proposalId);
|
uint256 proposalId = proposeAndVote(proposalAddress);
|
||||||
governance.execute(proposalId);
|
|
||||||
}
|
waitUntilExecutable(proposalId);
|
||||||
}
|
governance.execute(proposalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,69 +1,85 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import { MockProposal } from "./MockProposal.sol";
|
import { MockProposal } from "./MockProposal.sol";
|
||||||
import { console2 } from "@forge-std/console2.sol";
|
import { console2 } from "@forge-std/console2.sol";
|
||||||
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
|
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
|
||||||
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
|
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
|
||||||
import { TornadoStakingRewards } from "@root/v4-patch/TornadoStakingRewards.sol";
|
import { TornadoStakingRewards } from "@root/v4-patch/TornadoStakingRewards.sol";
|
||||||
|
|
||||||
contract TestContractsState is MockProposal {
|
contract TestContractsState is MockProposal {
|
||||||
function testLockedBalanceSaved() public {
|
function testLockedBalanceSaved() public {
|
||||||
uint256 lockedBalanceBeforeExecution = governance.lockedBalance(TEST_REAL_ADDRESS_WITH_BALANCE);
|
uint256 lockedBalanceBeforeExecution = governance.lockedBalance(TEST_REAL_ADDRESS_WITH_BALANCE);
|
||||||
console2.log("User locked balance before execution: %s TORN", lockedBalanceBeforeExecution / _tornDecimals);
|
console2.log("User locked balance before execution: %s TORN", lockedBalanceBeforeExecution / 10 ** 18);
|
||||||
|
|
||||||
createAndExecuteProposal();
|
createAndExecuteProposal();
|
||||||
|
|
||||||
uint256 lockedBalanceAfterExecution = governance.lockedBalance(TEST_REAL_ADDRESS_WITH_BALANCE);
|
uint256 lockedBalanceAfterExecution = governance.lockedBalance(TEST_REAL_ADDRESS_WITH_BALANCE);
|
||||||
console2.log("User locked balance before execution: %s TORN", lockedBalanceAfterExecution / _tornDecimals);
|
console2.log("User locked balance before execution: %s TORN", lockedBalanceAfterExecution / 10 ** 18);
|
||||||
|
|
||||||
require(lockedBalanceBeforeExecution == lockedBalanceAfterExecution, "Wrong locked balance after execution");
|
require(
|
||||||
}
|
lockedBalanceBeforeExecution == lockedBalanceAfterExecution,
|
||||||
|
"Wrong locked balance after execution"
|
||||||
function testGovernanceStakingStateChanged() public {
|
);
|
||||||
TornadoStakingRewards oldStaking = TornadoStakingRewards(getStakingProxyAddress());
|
}
|
||||||
uint256 accumulatedRewardsBeforeExecution = oldStaking.checkReward(TEST_REAL_ADDRESS_WITH_BALANCE);
|
|
||||||
console2.log("User rewards balance (bugged) before execution: %s TORN", accumulatedRewardsBeforeExecution / _tornDecimals);
|
function testGovernanceStakingStateChanged() public {
|
||||||
console2.log("Bugged value of accumulated rewards per TORN: %s", oldStaking.accumulatedRewardPerTorn());
|
TornadoStakingRewards oldStaking = TornadoStakingRewards(getStakingProxyAddress());
|
||||||
|
uint256 accumulatedRewardsBeforeExecution = oldStaking.checkReward(TEST_REAL_ADDRESS_WITH_BALANCE);
|
||||||
createAndExecuteProposal();
|
console2.log(
|
||||||
|
"User rewards balance (bugged) before execution: %s TORN",
|
||||||
TornadoStakingRewards newStaking = TornadoStakingRewards(getStakingProxyAddress());
|
accumulatedRewardsBeforeExecution / 10 ** 18
|
||||||
uint256 accumulatedRewardsPerTORNAfterExecution = newStaking.accumulatedRewardPerTorn();
|
);
|
||||||
uint256 accumulatedRewardsAfterExecution = newStaking.checkReward(TEST_REAL_ADDRESS_WITH_BALANCE);
|
console2.log(
|
||||||
|
"Bugged value of accumulated rewards per TORN: %s", oldStaking.accumulatedRewardPerTorn()
|
||||||
console2.log("User rewards balance before execution: %s TORN", accumulatedRewardsAfterExecution / _tornDecimals);
|
);
|
||||||
console2.log("Value of accumulated rewards per TORN after contract redeployment: %s", accumulatedRewardsPerTORNAfterExecution);
|
|
||||||
|
createAndExecuteProposal();
|
||||||
require(accumulatedRewardsBeforeExecution >= accumulatedRewardsAfterExecution, "Wtf");
|
|
||||||
require(accumulatedRewardsAfterExecution == 0, "Accumulated rewards isn't nullified");
|
TornadoStakingRewards newStaking = TornadoStakingRewards(getStakingProxyAddress());
|
||||||
require(accumulatedRewardsPerTORNAfterExecution == 0, "Accumulated rewards per TORN isn't nullified");
|
uint256 accumulatedRewardsPerTORNAfterExecution = newStaking.accumulatedRewardPerTorn();
|
||||||
}
|
uint256 accumulatedRewardsAfterExecution = newStaking.checkReward(TEST_REAL_ADDRESS_WITH_BALANCE);
|
||||||
|
|
||||||
function testRelayerRegistryStateSaved() public {
|
console2.log(
|
||||||
RelayerRegistry registry = RelayerRegistry(getRelayerRegistryProxyAddress());
|
"User rewards balance before execution: %s TORN", accumulatedRewardsAfterExecution / 10 ** 18
|
||||||
|
);
|
||||||
bool isRelayerRegisteredBeforeExecution = registry.isRelayer(TEST_RELAYER_ADDRESS);
|
console2.log(
|
||||||
uint256 relayerStakedBalanceBeforeExecution = registry.getRelayerBalance(TEST_RELAYER_ADDRESS);
|
"Value of accumulated rewards per TORN after contract redeployment: %s",
|
||||||
console2.log(
|
accumulatedRewardsPerTORNAfterExecution
|
||||||
"Relayer balance in relayer registry contract before proposal execution: %s TORN",
|
);
|
||||||
relayerStakedBalanceBeforeExecution / _tornDecimals
|
|
||||||
);
|
require(accumulatedRewardsBeforeExecution >= accumulatedRewardsAfterExecution, "Wtf");
|
||||||
|
require(accumulatedRewardsAfterExecution == 0, "Accumulated rewards isn't nullified");
|
||||||
require(isRelayerRegisteredBeforeExecution, "Relayer not registered");
|
require(accumulatedRewardsPerTORNAfterExecution == 0, "Accumulated rewards per TORN isn't nullified");
|
||||||
|
}
|
||||||
createAndExecuteProposal();
|
|
||||||
|
function testRelayerRegistryStateSaved() public {
|
||||||
bool isRelayerRegisteredAfterExecution = registry.isRelayer(TEST_RELAYER_ADDRESS);
|
RelayerRegistry registry = RelayerRegistry(getRelayerRegistryProxyAddress());
|
||||||
uint256 relayerStakedBalanceAfterExecution = registry.getRelayerBalance(TEST_RELAYER_ADDRESS);
|
|
||||||
|
bool isRelayerRegisteredBeforeExecution = registry.isRelayer(TEST_RELAYER_ADDRESS);
|
||||||
console2.log(
|
uint256 relayerStakedBalanceBeforeExecution = registry.getRelayerBalance(TEST_RELAYER_ADDRESS);
|
||||||
"Relayer balance in relayer registry contract after proposal execution: %s TORN",
|
console2.log(
|
||||||
relayerStakedBalanceAfterExecution / _tornDecimals
|
"Relayer balance in relayer registry contract before proposal execution: %s TORN",
|
||||||
);
|
relayerStakedBalanceBeforeExecution / 10 ** 18
|
||||||
|
);
|
||||||
require(isRelayerRegisteredAfterExecution, "Relayer isn't registered after proposal execution");
|
|
||||||
require(relayerStakedBalanceBeforeExecution == relayerStakedBalanceAfterExecution, "Relayer stake balance differs after execution");
|
require(isRelayerRegisteredBeforeExecution, "Relayer not registered");
|
||||||
}
|
|
||||||
}
|
createAndExecuteProposal();
|
||||||
|
|
||||||
|
bool isRelayerRegisteredAfterExecution = registry.isRelayer(TEST_RELAYER_ADDRESS);
|
||||||
|
uint256 relayerStakedBalanceAfterExecution = registry.getRelayerBalance(TEST_RELAYER_ADDRESS);
|
||||||
|
|
||||||
|
console2.log(
|
||||||
|
"Relayer balance in relayer registry contract after proposal execution: %s TORN",
|
||||||
|
relayerStakedBalanceAfterExecution / 10 ** 18
|
||||||
|
);
|
||||||
|
|
||||||
|
require(isRelayerRegisteredAfterExecution, "Relayer isn't registered after proposal execution");
|
||||||
|
require(
|
||||||
|
relayerStakedBalanceBeforeExecution == relayerStakedBalanceAfterExecution,
|
||||||
|
"Relayer stake balance differs after execution"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,7 +21,8 @@ contract TestProxyUpdating is MockProposal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getUpgradeableProxyImplementationAddress(address proxy) internal view returns (address) {
|
function getUpgradeableProxyImplementationAddress(address proxy) internal view returns (address) {
|
||||||
bytes32 proxyImplementationSlot = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);
|
bytes32 proxyImplementationSlot =
|
||||||
|
bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);
|
||||||
|
|
||||||
return getAddressFromSlot(proxy, proxyImplementationSlot);
|
return getAddressFromSlot(proxy, proxyImplementationSlot);
|
||||||
}
|
}
|
||||||
@ -36,25 +37,36 @@ contract TestProxyUpdating is MockProposal {
|
|||||||
|
|
||||||
function testGovernanceStakingProxyUpdated() public {
|
function testGovernanceStakingProxyUpdated() public {
|
||||||
address stakingProxyAddressBeforeExecution = getStakingProxyAddress();
|
address stakingProxyAddressBeforeExecution = getStakingProxyAddress();
|
||||||
console2.log("Staking proxy address before proposal execution: %s", stakingProxyAddressBeforeExecution);
|
console2.log(
|
||||||
|
"Staking proxy address before proposal execution: %s", stakingProxyAddressBeforeExecution
|
||||||
|
);
|
||||||
|
|
||||||
createAndExecuteProposal();
|
createAndExecuteProposal();
|
||||||
|
|
||||||
address stakingProxyAddressAfterExecution = getStakingProxyAddress();
|
address stakingProxyAddressAfterExecution = getStakingProxyAddress();
|
||||||
console2.log("Staking proxy address after proposal execution: %s", stakingProxyAddressAfterExecution);
|
console2.log("Staking proxy address after proposal execution: %s", stakingProxyAddressAfterExecution);
|
||||||
|
|
||||||
require(stakingProxyAddressBeforeExecution != stakingProxyAddressAfterExecution, "Staking proxy address didn't changed");
|
require(
|
||||||
|
stakingProxyAddressBeforeExecution != stakingProxyAddressAfterExecution,
|
||||||
|
"Staking proxy address didn't changed"
|
||||||
|
);
|
||||||
require(isContract(stakingProxyAddressAfterExecution));
|
require(isContract(stakingProxyAddressAfterExecution));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGovernanceStakingImplementationUpdated() public {
|
function testGovernanceStakingImplementationUpdated() public {
|
||||||
address stakingImplementationAddressBeforeExecution = getStakingImplementationAddress();
|
address stakingImplementationAddressBeforeExecution = getStakingImplementationAddress();
|
||||||
console2.log("Staking implementation address before proposal execution: %s", stakingImplementationAddressBeforeExecution);
|
console2.log(
|
||||||
|
"Staking implementation address before proposal execution: %s",
|
||||||
|
stakingImplementationAddressBeforeExecution
|
||||||
|
);
|
||||||
|
|
||||||
createAndExecuteProposal();
|
createAndExecuteProposal();
|
||||||
|
|
||||||
address stakingImplementationAddressAfterExecution = getStakingImplementationAddress();
|
address stakingImplementationAddressAfterExecution = getStakingImplementationAddress();
|
||||||
console2.log("Staking implementation address after proposal execution: %s", stakingImplementationAddressAfterExecution);
|
console2.log(
|
||||||
|
"Staking implementation address after proposal execution: %s",
|
||||||
|
stakingImplementationAddressAfterExecution
|
||||||
|
);
|
||||||
|
|
||||||
require(
|
require(
|
||||||
stakingImplementationAddressBeforeExecution != stakingImplementationAddressAfterExecution,
|
stakingImplementationAddressBeforeExecution != stakingImplementationAddressAfterExecution,
|
||||||
@ -64,33 +76,45 @@ contract TestProxyUpdating is MockProposal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function testRelayerRegistryImplementationUpdated() public {
|
function testRelayerRegistryImplementationUpdated() public {
|
||||||
address relayerRegistryImplementationAddressBeforeExecution = getRelayerRegistryImplementationAddress();
|
address relayerRegistryImplementationAddressBeforeExecution =
|
||||||
|
getRelayerRegistryImplementationAddress();
|
||||||
console2.log(
|
console2.log(
|
||||||
"Relayer registry implementation address before proposal execution: %s", relayerRegistryImplementationAddressBeforeExecution
|
"Relayer registry implementation address before proposal execution: %s",
|
||||||
|
relayerRegistryImplementationAddressBeforeExecution
|
||||||
);
|
);
|
||||||
|
|
||||||
createAndExecuteProposal();
|
createAndExecuteProposal();
|
||||||
|
|
||||||
address relayerRegistryImplementationAddressAfterExecution = getRelayerRegistryImplementationAddress();
|
address relayerRegistryImplementationAddressAfterExecution = getRelayerRegistryImplementationAddress();
|
||||||
console2.log(
|
console2.log(
|
||||||
"Relayer registry implementation address after proposal execution: %s", relayerRegistryImplementationAddressAfterExecution
|
"Relayer registry implementation address after proposal execution: %s",
|
||||||
|
relayerRegistryImplementationAddressAfterExecution
|
||||||
);
|
);
|
||||||
|
|
||||||
require(
|
require(
|
||||||
relayerRegistryImplementationAddressBeforeExecution != relayerRegistryImplementationAddressAfterExecution,
|
relayerRegistryImplementationAddressBeforeExecution
|
||||||
|
!= relayerRegistryImplementationAddressAfterExecution,
|
||||||
"Relayer registry implementation address didn't changed"
|
"Relayer registry implementation address didn't changed"
|
||||||
);
|
);
|
||||||
require(isContract(relayerRegistryImplementationAddressAfterExecution));
|
require(isContract(relayerRegistryImplementationAddressAfterExecution));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGovernanceImplementationUpdated() public {
|
function testGovernanceImplementationUpdated() public {
|
||||||
address governanceImplementationAddressBeforeExecution = getUpgradeableProxyImplementationAddress(_governanceAddress);
|
address governanceImplementationAddressBeforeExecution =
|
||||||
console2.log("Governance implementation address before proposal execution: %s", governanceImplementationAddressBeforeExecution);
|
getUpgradeableProxyImplementationAddress(_governanceAddress);
|
||||||
|
console2.log(
|
||||||
|
"Governance implementation address before proposal execution: %s",
|
||||||
|
governanceImplementationAddressBeforeExecution
|
||||||
|
);
|
||||||
|
|
||||||
createAndExecuteProposal();
|
createAndExecuteProposal();
|
||||||
|
|
||||||
address governanceImplementationAddressAfterExecution = getUpgradeableProxyImplementationAddress(_governanceAddress);
|
address governanceImplementationAddressAfterExecution =
|
||||||
console2.log("Governance implementation address after proposal execution: %s", governanceImplementationAddressAfterExecution);
|
getUpgradeableProxyImplementationAddress(_governanceAddress);
|
||||||
|
console2.log(
|
||||||
|
"Governance implementation address after proposal execution: %s",
|
||||||
|
governanceImplementationAddressAfterExecution
|
||||||
|
);
|
||||||
|
|
||||||
require(
|
require(
|
||||||
governanceImplementationAddressBeforeExecution != governanceImplementationAddressAfterExecution,
|
governanceImplementationAddressBeforeExecution != governanceImplementationAddressAfterExecution,
|
||||||
@ -101,12 +125,16 @@ contract TestProxyUpdating is MockProposal {
|
|||||||
|
|
||||||
function testRelayerRegistryProxyNotUpdated() public {
|
function testRelayerRegistryProxyNotUpdated() public {
|
||||||
address relayerRegistryProxyAddressBeforeExecution = getRelayerRegistryProxyAddress();
|
address relayerRegistryProxyAddressBeforeExecution = getRelayerRegistryProxyAddress();
|
||||||
console2.log("Relayer registry proxy before proposal execution: %s", relayerRegistryProxyAddressBeforeExecution);
|
console2.log(
|
||||||
|
"Relayer registry proxy before proposal execution: %s", relayerRegistryProxyAddressBeforeExecution
|
||||||
|
);
|
||||||
|
|
||||||
createAndExecuteProposal();
|
createAndExecuteProposal();
|
||||||
|
|
||||||
address relayerRegistryProxyAddressAfterExecution = getRelayerRegistryProxyAddress();
|
address relayerRegistryProxyAddressAfterExecution = getRelayerRegistryProxyAddress();
|
||||||
console2.log("Relayer registry proxyafter proposal execution: %s", relayerRegistryProxyAddressAfterExecution);
|
console2.log(
|
||||||
|
"Relayer registry proxyafter proposal execution: %s", relayerRegistryProxyAddressAfterExecution
|
||||||
|
);
|
||||||
|
|
||||||
require(
|
require(
|
||||||
relayerRegistryProxyAddressBeforeExecution == relayerRegistryProxyAddressAfterExecution,
|
relayerRegistryProxyAddressBeforeExecution == relayerRegistryProxyAddressAfterExecution,
|
||||||
|
@ -1,123 +1,127 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import { console2 } from "@forge-std/console2.sol";
|
import { console2 } from "@forge-std/console2.sol";
|
||||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
import { MockProposal } from "./MockProposal.sol";
|
import { MockProposal } from "./MockProposal.sol";
|
||||||
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
|
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
|
||||||
|
|
||||||
contract TestRelayerBalance is MockProposal {
|
contract TestRelayerBalance is MockProposal {
|
||||||
address[] internal allRelayersAddresses = [
|
address[] internal allRelayersAddresses = [
|
||||||
0x20BB3095a4852F4c97d7A188E9f7183C85AcfC49,
|
0x20BB3095a4852F4c97d7A188E9f7183C85AcfC49,
|
||||||
0x47b03dF2145CC9Eed6d8819E02D25590F297C603,
|
0x47b03dF2145CC9Eed6d8819E02D25590F297C603,
|
||||||
0xBe4d1e137A24af091be80Ae58d652279665e3A27,
|
0xBe4d1e137A24af091be80Ae58d652279665e3A27,
|
||||||
0x18F516dD6D5F46b2875Fd822B994081274be2a8b,
|
0x18F516dD6D5F46b2875Fd822B994081274be2a8b,
|
||||||
0x49136693081f2c18E2cF14428dD78cd90A22dC1f,
|
0x49136693081f2c18E2cF14428dD78cd90A22dC1f,
|
||||||
0xA0F0287683E820FF4211e67C03cf46a87431f4E1,
|
0xA0F0287683E820FF4211e67C03cf46a87431f4E1,
|
||||||
0xD6187b4a0f51355A36764558D39b2C21aC12393D,
|
0xD6187b4a0f51355A36764558D39b2C21aC12393D,
|
||||||
0x2ca1a9D6c79367EA1eA481FC0A5e8C5BD6C62d25,
|
0x2ca1a9D6c79367EA1eA481FC0A5e8C5BD6C62d25,
|
||||||
0x9f9f98e28456EEEFC4Af1c990a170e2B0D2d6027,
|
0x9f9f98e28456EEEFC4Af1c990a170e2B0D2d6027,
|
||||||
0xb326d1F0837E14Ad265397800eF3Bf7a538335E4,
|
0xb326d1F0837E14Ad265397800eF3Bf7a538335E4,
|
||||||
0xB5cD48dD89C063B5a3Fe1BCC325364be62fc0f00,
|
0xB5cD48dD89C063B5a3Fe1BCC325364be62fc0f00,
|
||||||
0x0F75C6BFAF436Eba0cB977Dcdfb0F30b57ff9D05,
|
0x0F75C6BFAF436Eba0cB977Dcdfb0F30b57ff9D05,
|
||||||
0x6a2D058890ccA15BEaEe5050caaAd56B2aB54DD4,
|
0x6a2D058890ccA15BEaEe5050caaAd56B2aB54DD4,
|
||||||
0x62E142F218585827436f59997C301F7040396AD4,
|
0x62E142F218585827436f59997C301F7040396AD4,
|
||||||
0x85972458dfBf9269567b2a27C4ffC958A4f24761,
|
0x85972458dfBf9269567b2a27C4ffC958A4f24761,
|
||||||
0x078AD5DB2151083Ec16eCA1b26e2C98f79034DA8,
|
0x078AD5DB2151083Ec16eCA1b26e2C98f79034DA8,
|
||||||
0x3514Cfd42E4DDe9E65e283EbdBfa2888117823A6,
|
0x3514Cfd42E4DDe9E65e283EbdBfa2888117823A6,
|
||||||
0x550c9288310482F593602dD3e426603ae00BC352,
|
0x550c9288310482F593602dD3e426603ae00BC352,
|
||||||
0x3884e9b1E2b0f8D00666c9767B5602B709EeEE06,
|
0x3884e9b1E2b0f8D00666c9767B5602B709EeEE06,
|
||||||
0xc6C86Aa348Eaa0ef1b6F8Da90C279b670e67A55D,
|
0xc6C86Aa348Eaa0ef1b6F8Da90C279b670e67A55D,
|
||||||
0x9f340Bf3791809293DC50321Bd7F4c19120a98B6,
|
0x9f340Bf3791809293DC50321Bd7F4c19120a98B6,
|
||||||
0xF6CB46F9c2E34cD4B7f374D225e0aE5F474DdB32,
|
0xF6CB46F9c2E34cD4B7f374D225e0aE5F474DdB32,
|
||||||
0x076D4E32C6A5D888fC4658281539c94E778C796d,
|
0x076D4E32C6A5D888fC4658281539c94E778C796d,
|
||||||
0x28907F21F43B419F34226d6f10aCbCf1832b1D4d,
|
0x28907F21F43B419F34226d6f10aCbCf1832b1D4d,
|
||||||
0x6289C8a70EE2Ed6914834CaEa431F9a82c7eAf70,
|
0x6289C8a70EE2Ed6914834CaEa431F9a82c7eAf70,
|
||||||
0xE6B23CBae6a62f4b52A021B76E7811522eb82055,
|
0xE6B23CBae6a62f4b52A021B76E7811522eb82055,
|
||||||
0xAF02873D7dF5f3e6D5fF42F622F4e138A68208e7,
|
0xAF02873D7dF5f3e6D5fF42F622F4e138A68208e7,
|
||||||
0xb9C612760dC5456e5979393Cfe4AB1fF270AE9e5,
|
0xb9C612760dC5456e5979393Cfe4AB1fF270AE9e5,
|
||||||
0xa56963fe9F46C758B2D0616A754346A8F9eba30b,
|
0xa56963fe9F46C758B2D0616A754346A8F9eba30b,
|
||||||
0x56be1F8196cC4AefCe3348E679a2008496D14473,
|
0x56be1F8196cC4AefCe3348E679a2008496D14473,
|
||||||
0x63606C4011e97a73BCd844Cde6a38D45a728BC0E,
|
0x63606C4011e97a73BCd844Cde6a38D45a728BC0E,
|
||||||
0xE939c61Acd8bD30366435C6B1033251117851b03,
|
0xE939c61Acd8bD30366435C6B1033251117851b03,
|
||||||
0x3e9979106DA74AFB64b866218AeB47F224A312bb,
|
0x3e9979106DA74AFB64b866218AeB47F224A312bb,
|
||||||
0x28f1a9b8e3941C0909059eB84E5834154A99E0fC,
|
0x28f1a9b8e3941C0909059eB84E5834154A99E0fC,
|
||||||
0x9c8C81f3F5C19DFfeE7257Dd7477b8ef6E405e82,
|
0x9c8C81f3F5C19DFfeE7257Dd7477b8ef6E405e82,
|
||||||
0x644D4f3b293a7fc86eB4EFB6Bd2439f7603C991D,
|
0x644D4f3b293a7fc86eB4EFB6Bd2439f7603C991D,
|
||||||
0x25De357c61c9f2711A605b66E83887BA5Fd22ac1,
|
0x25De357c61c9f2711A605b66E83887BA5Fd22ac1,
|
||||||
0x78c88fF43cd503316e8A15B6d92b2EBFa73802B2,
|
0x78c88fF43cd503316e8A15B6d92b2EBFa73802B2,
|
||||||
0x2C42550Ff1Bdc139b54C5042a9a86A56398E9d83,
|
0x2C42550Ff1Bdc139b54C5042a9a86A56398E9d83,
|
||||||
0xf18673Ab6Eb72937607aA8388b8f7aa0AC3a0D32,
|
0xf18673Ab6Eb72937607aA8388b8f7aa0AC3a0D32,
|
||||||
0x3a1d526D09b7E59Fd88De4726f68A8246dDC2742,
|
0x3a1d526D09b7E59Fd88De4726f68A8246dDC2742,
|
||||||
0x7Ba6781620c91676B070D319E7E894BFd4A9eC81,
|
0x7Ba6781620c91676B070D319E7E894BFd4A9eC81,
|
||||||
0x9Ffbd3f9eE795A4fDa880ED553A2A4BD6D45CE5B,
|
0x9Ffbd3f9eE795A4fDa880ED553A2A4BD6D45CE5B,
|
||||||
0xe6184DA55174Cc0263a17eA2fc24E48511766505,
|
0xe6184DA55174Cc0263a17eA2fc24E48511766505,
|
||||||
0x36989535F0290eaC96692675cbf15a3BD2f42E46,
|
0x36989535F0290eaC96692675cbf15a3BD2f42E46,
|
||||||
0x12D92FeD171F16B3a05ACB1542B40648E7CEd384,
|
0x12D92FeD171F16B3a05ACB1542B40648E7CEd384,
|
||||||
0x08657a1f4C1F06d657F31767831421EE7FaDf549,
|
0x08657a1f4C1F06d657F31767831421EE7FaDf549,
|
||||||
0x42FecB4137aFF76E0E85702ff4F339DbFe6D859E,
|
0x42FecB4137aFF76E0E85702ff4F339DbFe6D859E,
|
||||||
0xc6e531CF18afE3a64bE19e40ac410f39FC9738da,
|
0xc6e531CF18afE3a64bE19e40ac410f39FC9738da,
|
||||||
0x9Ee26a4bFd731E8e742B65bF955814EADdd7F151,
|
0x9Ee26a4bFd731E8e742B65bF955814EADdd7F151,
|
||||||
0x7E3893725d4e238B4c8c83375bBAd024a66Ffa42,
|
0x7E3893725d4e238B4c8c83375bBAd024a66Ffa42,
|
||||||
0x465403d43f48Dfaa3F9385B60F0fEa36c360C18A,
|
0x465403d43f48Dfaa3F9385B60F0fEa36c360C18A,
|
||||||
0xc7285e85a6D11C762A7D9C57aC38E31A671E9777,
|
0xc7285e85a6D11C762A7D9C57aC38E31A671E9777,
|
||||||
0x74b6ea6B2EeFd3eF4da5E8c4C0480776035029c2,
|
0x74b6ea6B2EeFd3eF4da5E8c4C0480776035029c2,
|
||||||
0x14812AE927e2BA5aA0c0f3C0eA016b3039574242,
|
0x14812AE927e2BA5aA0c0f3C0eA016b3039574242,
|
||||||
0xdc957b6a3F630bEf2E6104C1a22dAeF9650b5349,
|
0xdc957b6a3F630bEf2E6104C1a22dAeF9650b5349,
|
||||||
0x1247749d7E28D357B4279110af0802603AC526cE,
|
0x1247749d7E28D357B4279110af0802603AC526cE,
|
||||||
0x1036AF02bCDb2e3A4db2d3D40b29e5054EDc79BA,
|
0x1036AF02bCDb2e3A4db2d3D40b29e5054EDc79BA,
|
||||||
0x3665B1E938Ce90c48502303ACB5049Fb065D3a85,
|
0x3665B1E938Ce90c48502303ACB5049Fb065D3a85,
|
||||||
0x87BeDf6AD81A2907633Ab68D02c44f0415bc68C1,
|
0x87BeDf6AD81A2907633Ab68D02c44f0415bc68C1,
|
||||||
0x0B45840cCEE39aeEfFDF621633d24AA8930B834c,
|
0x0B45840cCEE39aeEfFDF621633d24AA8930B834c,
|
||||||
0xcBD78860218160F4b463612f30806807Fe6E804C,
|
0xcBD78860218160F4b463612f30806807Fe6E804C,
|
||||||
0xa42303EE9B2eC1DB7E2a86Ed6C24AF7E49E9e8B9,
|
0xa42303EE9B2eC1DB7E2a86Ed6C24AF7E49E9e8B9,
|
||||||
0xa0109274F53609f6Be97ec5f3052C659AB80f012,
|
0xa0109274F53609f6Be97ec5f3052C659AB80f012,
|
||||||
0xb578603D3fB9216158c29488c1A902Dd0300c115,
|
0xb578603D3fB9216158c29488c1A902Dd0300c115,
|
||||||
0x7b81b8680b1abd1e2E983a1589DeB5468B50A544,
|
0x7b81b8680b1abd1e2E983a1589DeB5468B50A544,
|
||||||
0x4750BCfcC340AA4B31be7e71fa072716d28c29C5,
|
0x4750BCfcC340AA4B31be7e71fa072716d28c29C5,
|
||||||
0x36DD7b862746fdD3eDd3577c8411f1B76FDC2Af5,
|
0x36DD7b862746fdD3eDd3577c8411f1B76FDC2Af5,
|
||||||
0x0D13F55BA1509352F9e36190d948D7c45B854Be2,
|
0x0D13F55BA1509352F9e36190d948D7c45B854Be2,
|
||||||
0x4803c6ec3E61cD1bb1735bBDdB21732100AA13cc,
|
0x4803c6ec3E61cD1bb1735bBDdB21732100AA13cc,
|
||||||
0x1ee815AD4a914c2C2f4650b3ED34978F8Fe2fcC4,
|
0x1ee815AD4a914c2C2f4650b3ED34978F8Fe2fcC4,
|
||||||
0x04843E2C74018c8d94f1834a7ccB94c16691E451,
|
0x04843E2C74018c8d94f1834a7ccB94c16691E451,
|
||||||
0x0000208a6cC0299dA631C08fE8c2EDe435Ea83B8,
|
0x0000208a6cC0299dA631C08fE8c2EDe435Ea83B8,
|
||||||
0x853281B7676DFB66B87e2f26c9cB9D10Ce883F37,
|
0x853281B7676DFB66B87e2f26c9cB9D10Ce883F37,
|
||||||
0xaaaaD0b504B4CD22348C4Db1071736646Aa314C6,
|
0xaaaaD0b504B4CD22348C4Db1071736646Aa314C6,
|
||||||
0x5a0cB6505B3b99dD4035bb1Ac43cC51202d4e29F,
|
0x5a0cB6505B3b99dD4035bb1Ac43cC51202d4e29F,
|
||||||
0x7171717171866B60cc1A76A058ae20C8F703AE05,
|
0x7171717171866B60cc1A76A058ae20C8F703AE05,
|
||||||
0x30F96AEF199B399B722F8819c9b0723016CEAe6C,
|
0x30F96AEF199B399B722F8819c9b0723016CEAe6C,
|
||||||
0xEFa22d23de9f293B11e0c4aC865d7b440647587a,
|
0xEFa22d23de9f293B11e0c4aC865d7b440647587a,
|
||||||
0xC0F12799B8D3FA8810DfE1616095170C72117F8F,
|
0xC0F12799B8D3FA8810DfE1616095170C72117F8F,
|
||||||
0x996ad81FD83eD7A87FD3D03694115dff19db0B3b,
|
0x996ad81FD83eD7A87FD3D03694115dff19db0B3b,
|
||||||
0x000000Cd6521Ed1a65FAe0678eA15aF4EEAD74fe,
|
0x000000Cd6521Ed1a65FAe0678eA15aF4EEAD74fe,
|
||||||
0x15980A3Bd6ed317f42d2eD0DCf3d3D730b6Bc0C5,
|
0x15980A3Bd6ed317f42d2eD0DCf3d3D730b6Bc0C5,
|
||||||
0x7853E027F37830790685622cdd8685fF0c8255A2,
|
0x7853E027F37830790685622cdd8685fF0c8255A2,
|
||||||
0xf0D9b969925116074eF43e7887Bcf035Ff1e7B19,
|
0xf0D9b969925116074eF43e7887Bcf035Ff1e7B19,
|
||||||
0x97096F56B09F6aaA4230eec3BA33249995690B0E,
|
0x97096F56B09F6aaA4230eec3BA33249995690B0E,
|
||||||
0x5555555731006f71f121144534Ca7C8799F66AA3,
|
0x5555555731006f71f121144534Ca7C8799F66AA3,
|
||||||
0x5007565e69E5c23C278c2e976beff38eF4D27B3d,
|
0x5007565e69E5c23C278c2e976beff38eF4D27B3d,
|
||||||
0x2ffAc4D796261ba8964d859867592B952b9FC158,
|
0x2ffAc4D796261ba8964d859867592B952b9FC158,
|
||||||
0xCEdac436cEA98E93F471331eCC693fF41D730921,
|
0xCEdac436cEA98E93F471331eCC693fF41D730921,
|
||||||
0x94596B6A626392F5D972D6CC4D929a42c2f0008c,
|
0x94596B6A626392F5D972D6CC4D929a42c2f0008c,
|
||||||
0x065f2A0eF62878e8951af3c387E4ddC944f1B8F4,
|
0x065f2A0eF62878e8951af3c387E4ddC944f1B8F4,
|
||||||
0xe7c490986FC34248F77b813eD6C8971e76e0384C,
|
0xe7c490986FC34248F77b813eD6C8971e76e0384C,
|
||||||
0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c
|
0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c
|
||||||
];
|
];
|
||||||
|
|
||||||
function testRelayerBalancesSum() public view {
|
function testRelayerBalancesSum() public view {
|
||||||
RelayerRegistry registry = RelayerRegistry(getRelayerRegistryProxyAddress());
|
RelayerRegistry registry = RelayerRegistry(getRelayerRegistryProxyAddress());
|
||||||
uint256 relayersBalancesSum;
|
uint256 relayersBalancesSum;
|
||||||
|
|
||||||
for (uint256 i = 0; i < allRelayersAddresses.length; i++) {
|
for (uint256 i = 0; i < allRelayersAddresses.length; i++) {
|
||||||
uint256 currentRelayerBalance = registry.getRelayerBalance(allRelayersAddresses[i]);
|
uint256 currentRelayerBalance = registry.getRelayerBalance(allRelayersAddresses[i]);
|
||||||
relayersBalancesSum += currentRelayerBalance;
|
relayersBalancesSum += currentRelayerBalance;
|
||||||
console2.log("Relayer %s, relayer balance: %s TORN", allRelayersAddresses[i], currentRelayerBalance / _tornDecimals);
|
console2.log(
|
||||||
}
|
"Relayer %s, relayer balance: %s TORN", allRelayersAddresses[i], currentRelayerBalance / 10e17
|
||||||
|
);
|
||||||
console2.log("\nSum of relayer balances on block %s: %s TORN", block.number, relayersBalancesSum / _tornDecimals);
|
}
|
||||||
|
|
||||||
require(relayersBalancesSum > 0);
|
console2.log(
|
||||||
}
|
"\nSum of relayer balances on block %s: %s TORN", block.number, relayersBalancesSum / 10e17
|
||||||
}
|
);
|
||||||
|
|
||||||
|
require(relayersBalancesSum > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,100 +1,130 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.6.12;
|
pragma solidity ^0.6.12;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import { console2 } from "@forge-std/console2.sol";
|
import { console2 } from "@forge-std/console2.sol";
|
||||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
import { MockProposal } from "./MockProposal.sol";
|
import { MockProposal } from "./MockProposal.sol";
|
||||||
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
|
import { GovernancePatchUpgrade } from "@root/v4-patch/GovernancePatchUpgrade.sol";
|
||||||
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
|
import { RelayerRegistry } from "@root/v4-patch/RelayerRegistry.sol";
|
||||||
import { TornadoStakingRewards } from "@root/v4-patch/TornadoStakingRewards.sol";
|
import { TornadoStakingRewards } from "@root/v4-patch/TornadoStakingRewards.sol";
|
||||||
|
|
||||||
contract TestGovernanceStakingRewards is MockProposal {
|
contract TestGovernanceStakingRewards is MockProposal {
|
||||||
function burnTokens(address caller, uint256 amount, TornadoStakingRewards staking) internal {
|
modifier replenishGovernanceStakingBalanceBefore() {
|
||||||
vm.startPrank(caller);
|
vm.startPrank(_governanceAddress);
|
||||||
staking.addBurnRewards(amount);
|
IERC20(_tokenAddress).transfer(getStakingProxyAddress(), 100_000 ether);
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
}
|
_;
|
||||||
|
}
|
||||||
function testAccumulatedRewardCanBeUpdated() public executeAttackerProposalBefore executeCurrentProposalBefore {
|
|
||||||
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
function burnTokens(address caller, uint256 amount, TornadoStakingRewards staking) internal {
|
||||||
|
vm.startPrank(caller);
|
||||||
uint256 accumulatedRewardPerTornBeforeBurning = staking.accumulatedRewardPerTorn() / _tornMaximumSupply;
|
staking.addBurnRewards(amount);
|
||||||
|
vm.stopPrank();
|
||||||
console2.log(
|
}
|
||||||
"Accumulated reward per TORN right after proposal execution: %s TORN", accumulatedRewardPerTornBeforeBurning / _tornDecimals
|
|
||||||
);
|
function testAccumulatedRewardCanBeUpdated()
|
||||||
|
public
|
||||||
burnTokens(_governanceAddress, 10_000_000 ether, staking);
|
executeAttackerProposalBefore
|
||||||
|
executeCurrentProposalBefore
|
||||||
uint256 accumulatedRewardPerTornAfterBurning = staking.accumulatedRewardPerTorn() / _tornMaximumSupply;
|
{
|
||||||
|
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
||||||
console2.log(
|
|
||||||
"Accumulated reward per TORN after burning 10 000 000 TORN: ~ %s TORN", accumulatedRewardPerTornAfterBurning / _tornDecimals
|
uint256 accumulatedRewardPerTornBeforeBurning =
|
||||||
);
|
staking.accumulatedRewardPerTorn() / _tornMaximumSupply;
|
||||||
|
|
||||||
require(accumulatedRewardPerTornAfterBurning > accumulatedRewardPerTornBeforeBurning, "Staking rewards isn't updated");
|
console2.log(
|
||||||
}
|
"Accumulated reward per TORN right after proposal execution: %s TORN",
|
||||||
|
accumulatedRewardPerTornBeforeBurning / 10e17
|
||||||
function testStakerCanGetRewards() public executeAttackerProposalBefore executeCurrentProposalBefore {
|
);
|
||||||
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
|
||||||
IERC20 TORN = IERC20(_tokenAddress);
|
burnTokens(_governanceAddress, 10_000_000 ether, staking);
|
||||||
|
|
||||||
uint256 toBurn = 10_000 ether;
|
uint256 accumulatedRewardPerTornAfterBurning = staking.accumulatedRewardPerTorn() / _tornMaximumSupply;
|
||||||
|
|
||||||
// Remind that we have locked in Governance 25 000 TORN for TEST_ADDRESS_ONE while voting
|
console2.log(
|
||||||
uint256 stakerLockedBalance = governance.lockedBalance(TEST_ADDRESS_ONE);
|
"Accumulated reward per TORN after burning 10 000 000 TORN: ~ %s TORN",
|
||||||
require(stakerLockedBalance == 25_000 ether, "Invalid test staker locked balance");
|
accumulatedRewardPerTornAfterBurning / 10e17
|
||||||
|
);
|
||||||
uint256 stakerRewardsBeforeBurning = staking.checkReward(TEST_ADDRESS_ONE);
|
|
||||||
console2.log("Staking rewards before burning: %s TORN", stakerRewardsBeforeBurning / _tornDecimals);
|
require(
|
||||||
|
accumulatedRewardPerTornAfterBurning > accumulatedRewardPerTornBeforeBurning,
|
||||||
burnTokens(_governanceAddress, toBurn, staking);
|
"Staking rewards isn't updated"
|
||||||
|
);
|
||||||
uint256 stakerRewardsAfterBurning = staking.checkReward(TEST_ADDRESS_ONE);
|
}
|
||||||
console2.log("Staking rewards after burning 10 000 TORN: %s TORN\n", stakerRewardsAfterBurning / _tornDecimals);
|
|
||||||
require(stakerRewardsAfterBurning > stakerRewardsBeforeBurning, "Rewards isn't changed after burning");
|
function testStakerCanGetRewards()
|
||||||
|
public
|
||||||
// All TORN, locked by users in Governance, is on the userVault contract balance
|
executeAttackerProposalBefore
|
||||||
uint256 governanceLockedAmount = TORN.balanceOf(address(governance.userVault()));
|
executeCurrentProposalBefore
|
||||||
uint256 receivedReward = stakerRewardsAfterBurning - stakerRewardsBeforeBurning;
|
replenishGovernanceStakingBalanceBefore
|
||||||
uint256 expectedRewards = stakerLockedBalance * toBurn / governanceLockedAmount;
|
{
|
||||||
|
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
||||||
console2.log("Expected staking rewards: %s TORN", expectedRewards / _tornDecimals);
|
IERC20 TORN = IERC20(_tokenAddress);
|
||||||
console2.log("Staker received rewards: %s TORN\n", receivedReward / _tornDecimals);
|
|
||||||
|
uint256 toBurn = 10_000 ether;
|
||||||
require(receivedReward == expectedRewards, "Expected and received rewards don't match");
|
|
||||||
|
// Remind that we have locked in Governance 25 000 TORN for TEST_ADDRESS_ONE while voting
|
||||||
uint256 stakerTORNbalanceBeforeGettingRewards = TORN.balanceOf(TEST_ADDRESS_ONE);
|
uint256 stakerLockedBalance = governance.lockedBalance(TEST_ADDRESS_ONE);
|
||||||
console2.log(
|
require(stakerLockedBalance == 25_000 ether, "Invalid test staker locked balance");
|
||||||
"Staker balance before getting (withdrawal) collected rewards: %s TORN", stakerTORNbalanceBeforeGettingRewards / _tornDecimals
|
|
||||||
);
|
uint256 stakerRewardsBeforeBurning = staking.checkReward(TEST_ADDRESS_ONE);
|
||||||
|
console2.log("Staking rewards before burning: %s TORN", stakerRewardsBeforeBurning / 10e17);
|
||||||
vm.startPrank(TEST_ADDRESS_ONE);
|
|
||||||
staking.getReward();
|
burnTokens(_governanceAddress, toBurn, staking);
|
||||||
vm.stopPrank();
|
|
||||||
|
uint256 stakerRewardsAfterBurning = staking.checkReward(TEST_ADDRESS_ONE);
|
||||||
uint256 stakerTORNbalanceAfterGettingRewards = TORN.balanceOf(TEST_ADDRESS_ONE);
|
console2.log("Staking rewards after burning 10 000 TORN: %s TORN", stakerRewardsAfterBurning / 10e17);
|
||||||
console2.log(
|
require(stakerRewardsAfterBurning > stakerRewardsBeforeBurning, "Rewards isn't changed after burning");
|
||||||
"Staker balance after getting (withdrawal) collected rewards: %s TORN", stakerTORNbalanceAfterGettingRewards / _tornDecimals
|
|
||||||
);
|
// All TORN, locked by users in Governance, is on the userVault contract balance
|
||||||
|
uint256 governanceLockedAmount = TORN.balanceOf(address(governance.userVault()));
|
||||||
require(stakerTORNbalanceAfterGettingRewards > stakerTORNbalanceBeforeGettingRewards, "Rewards isn't withdrawed");
|
uint256 receivedReward = stakerRewardsAfterBurning - stakerRewardsBeforeBurning;
|
||||||
require(
|
uint256 expectedRewards = stakerLockedBalance * toBurn / governanceLockedAmount;
|
||||||
stakerTORNbalanceAfterGettingRewards - stakerTORNbalanceBeforeGettingRewards == receivedReward,
|
|
||||||
"Incorrect rewards amount withdrawed"
|
console2.log("Expected staking rewards: %s TORN", expectedRewards / 10e17);
|
||||||
);
|
console2.log("Staker received rewards: %s TORN", receivedReward / 10e17);
|
||||||
}
|
|
||||||
|
require(receivedReward == expectedRewards, "Expected and received rewards don't match");
|
||||||
function testCanBurnFromRelayerRegistry() public executeAttackerProposalBefore executeCurrentProposalBefore {
|
|
||||||
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
uint256 stakerTORNbalanceBeforeGettingRewards = TORN.balanceOf(TEST_ADDRESS_ONE);
|
||||||
address relayerRegistryAddress = getRelayerRegistryProxyAddress();
|
console2.log(
|
||||||
|
"Staker balance before getting (withdrawal) collected rewards: %s TORN",
|
||||||
uint256 accumulatedRewardPerTornBeforeBurning = staking.accumulatedRewardPerTorn();
|
stakerTORNbalanceBeforeGettingRewards / 10e17
|
||||||
|
);
|
||||||
burnTokens(relayerRegistryAddress, 10_000 ether, staking);
|
|
||||||
|
vm.startPrank(TEST_ADDRESS_ONE);
|
||||||
require(staking.accumulatedRewardPerTorn() > accumulatedRewardPerTornBeforeBurning, "Burn from relayer registry failed");
|
staking.getReward();
|
||||||
}
|
vm.stopPrank();
|
||||||
}
|
|
||||||
|
uint256 stakerTORNbalanceAfterGettingRewards = TORN.balanceOf(TEST_ADDRESS_ONE);
|
||||||
|
console2.log(
|
||||||
|
"Staker balance after getting (withdrawal) collected rewards: %s TORN",
|
||||||
|
stakerTORNbalanceAfterGettingRewards / 10e17
|
||||||
|
);
|
||||||
|
|
||||||
|
require(
|
||||||
|
stakerTORNbalanceAfterGettingRewards > stakerTORNbalanceBeforeGettingRewards,
|
||||||
|
"Rewards isn't withdrawed"
|
||||||
|
);
|
||||||
|
require(
|
||||||
|
stakerTORNbalanceAfterGettingRewards - stakerTORNbalanceBeforeGettingRewards == receivedReward,
|
||||||
|
"Incorrect rewards amount withdrawed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCanBurnFromRelayerRegistry() public {
|
||||||
|
TornadoStakingRewards staking = TornadoStakingRewards(getStakingProxyAddress());
|
||||||
|
address relayerRegistryAddress = getRelayerRegistryProxyAddress();
|
||||||
|
|
||||||
|
uint256 accumulatedRewardPerTornBeforeBurning = staking.accumulatedRewardPerTorn();
|
||||||
|
|
||||||
|
burnTokens(relayerRegistryAddress, 10_000 ether, staking);
|
||||||
|
|
||||||
|
require(
|
||||||
|
staking.accumulatedRewardPerTorn() > accumulatedRewardPerTornBeforeBurning,
|
||||||
|
"Burn from relayer registry failed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,7 +7,5 @@ contract Parameters {
|
|||||||
address constant _governanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
address constant _governanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
||||||
address constant _governanceVaultAddress = 0x2F50508a8a3D323B91336FA3eA6ae50E55f32185;
|
address constant _governanceVaultAddress = 0x2F50508a8a3D323B91336FA3eA6ae50E55f32185;
|
||||||
address constant _tokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
address constant _tokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
||||||
|
|
||||||
uint256 constant _tornMaximumSupply = 10_000_000;
|
uint256 constant _tornMaximumSupply = 10_000_000;
|
||||||
uint256 constant _tornDecimals = 1e18;
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user