proposal-31-finalize-decent.../test/UpdateENSDataProposal.t.sol
2023-10-18 08:11:34 -07:00

117 lines
5.5 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import { ProposalUtils } from "./utils/ProposalUtils.sol";
import { UpdateENSDataProposal } from "@root/UpdateENSDataProposal.sol";
import { console2 } from "@forge-std/console2.sol";
import { IENSResolver } from "@interfaces/IENSResolver.sol";
import { IENSRegistry } from "@interfaces/IENSRegistry.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "node_modules/base58-solidity/contracts/Base58.sol";
import { ENSNamehash } from "./ENSNamehash.sol";
contract TestExampleProposal is ProposalUtils {
using ENSNamehash for bytes;
IENSResolver internal ensResolver = IENSResolver(0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41);
IENSRegistry ensRegistry = IENSRegistry(ENSAddress);
modifier executeCurrentProposalBefore() {
createAndExecuteProposal();
_;
}
function calculateDomainNode(string memory domain) internal pure returns (bytes32) {
return ENSNamehash.namehash(bytes(domain));
}
function calculateIpfsContenthash(string memory ipfsCid) internal pure returns (bytes memory) {
if (bytes(ipfsCid).length == 0) return bytes("");
return bytes.concat(hex"e3010170", Base58.decodeFromString(ipfsCid));
}
function createAndExecuteProposal() public {
address proposalAddress = address(new UpdateENSDataProposal());
proposeAndExecute(proposalAddress);
}
struct DomainInfo {
string ensName;
string ipfsCid;
}
DomainInfo[] subdomains = [
DomainInfo("sources.tornadocash.eth", "QmQ8T782t6TDFKoZLeVeQaHabgaGjNnTGk86zKMPE4uHtx"),
DomainInfo("download.sources.tornadocash.eth", "QmXzf2Lymv1YStHiiMaFrEDxkD4o4cN8cdS6N82voSaTpv"),
DomainInfo("help.sources.tornadocash.eth", "QmPBfNYr7hWtpUGNbTgYzaXa6wPp5HcEysZH7pNn9zyEqe"),
DomainInfo("relayers-ui.tornadocash.eth", "QmTuGF7kKRjWRjmbxg5qMox622T2VftYiZWKjRpRvYkUN6"),
DomainInfo("relayers-network.tornadocash.eth", "QmTuGF7kKRjWRjmbxg5qMox622T2VftYiZWKjRpRvYkUN6"),
DomainInfo("relayers-ui.sources.tornadocash.eth", "QmW535jPAscFPqh5M38YjLcwJDJjBrT6ZRtqQqCPF19SzF"),
DomainInfo("relayer.sources.tornadocash.eth", "QmVLBoVZAkigrf7x1VHx4aeCHMX5HFwa9cmKGEcC1eUP9i"),
DomainInfo("docs.sources.tornadocash.eth", "QmZ7tLxVF5nwmTNwq61MMf7gnUxh85t5Rs6ixxcwu1gRay"),
DomainInfo("docs.tornadocash.eth", "QmUtXxMHnLGxsG3Mqm3hhQ2rByFsehSqS57LiEKpEdEiHR")
];
function testSubdomainsRegistered() public executeCurrentProposalBefore {
for (uint256 i = 0; i < subdomains.length; i++) {
bytes32 node = calculateDomainNode(subdomains[i].ensName);
bool isRegistered = ensRegistry.recordExists(node);
if (isRegistered) {
console2.log("Subdomain %s registered", subdomains[i].ensName);
} else {
console2.log("Subdomain %s isn't registered!", subdomains[i].ensName);
}
require(isRegistered, "subdomain not registered");
}
}
function testContenthashesOnSubdomainsAreCorrect() public executeCurrentProposalBefore {
for (uint256 i = 0; i < subdomains.length; i++) {
bytes32 node = calculateDomainNode(subdomains[i].ensName);
bytes memory desiredIpfsContenthash = calculateIpfsContenthash(subdomains[i].ipfsCid);
bytes memory realContenthash = ensResolver.contenthash(node);
assertEq(desiredIpfsContenthash, realContenthash, "contenthash is wrong");
}
}
function testOwnerOfAllSubdomainsIsGovernance() public executeCurrentProposalBefore {
for (uint256 i = 0; i < subdomains.length; i++) {
bytes32 node = calculateDomainNode(subdomains[i].ensName);
require(ensRegistry.owner(node) == governanceAddress, "owner is not governance");
}
}
function testUsdtTransferredToDeveloper() public {
bytes32 tornadoDeveloperENSNode = calculateDomainNode("tornado-dev.eth");
address tornadoDeveloperAddress = IENSResolver(ensRegistry.resolver(tornadoDeveloperENSNode)).addr(tornadoDeveloperENSNode);
address usdtTokenAddress = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
uint256 usdtDecimals = 1e6;
IERC20 usdt = IERC20(usdtTokenAddress);
uint256 developerBalanceBeforeProposal = usdt.balanceOf(tornadoDeveloperAddress);
uint256 tornContractBalanceBeforeProposal = usdt.balanceOf(tornTokenAddress);
console2.log("Torn contract usdt balance before proposal execution: %s USDT", tornContractBalanceBeforeProposal / usdtDecimals);
console2.log("Usdt balance on developer address before proposal execution: %s", developerBalanceBeforeProposal / usdtDecimals);
require(developerBalanceBeforeProposal == 0 && tornContractBalanceBeforeProposal > 1500, "wrong usdt balance before proposal");
createAndExecuteProposal();
uint256 developerBalanceAfterProposal = usdt.balanceOf(tornadoDeveloperAddress);
uint256 tornContractBalanceAfterProposal = usdt.balanceOf(tornTokenAddress);
console2.log("Torn contract usdt balance after proposal exectuion: %s USDT", tornContractBalanceAfterProposal / usdtDecimals);
console2.log("Usdt balance on developer address after proposal execution: %s", developerBalanceAfterProposal / usdtDecimals);
require(
developerBalanceAfterProposal == tornContractBalanceBeforeProposal && tornContractBalanceAfterProposal == 0,
"wrong usdt balance after proposal"
);
}
}