tornado-contracts/contracts/Unaudited/InfoRegistry.sol

282 lines
7.4 KiB
Solidity
Raw Permalink Normal View History

2024-12-26 02:18:47 +00:00
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
2025-01-05 09:29:24 +00:00
import { EnumerableSet } from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
2024-12-26 02:18:47 +00:00
/**
* @dev Tornado Cash info registry for multi-chain
*/
contract InfoRegistry {
using EnumerableSet for EnumerableSet.Bytes32Set;
struct RpcInfo {
uint64 chainId;
string url;
bool isPrior;
}
struct TokenInfo {
uint64 chainId;
address addr;
string name;
string symbol;
uint8 decimals;
uint32 transferGas;
}
struct InstanceInfo {
uint64 chainId;
address addr;
uint256 denomination;
address tokenAddress;
bool instanceApproval;
bool isOptional;
bool isDisabled;
}
event BumpedRevision(uint16 indexed newRevision);
event AddedChain(uint16 indexed revision, uint64 indexed chainId, bytes netInfo);
2025-01-05 09:29:24 +00:00
event AddedRpc(uint64 indexed chainId, string url, bool indexed isPrior);
event RemovedRpc(uint64 indexed chainId, string url, bool indexed isPrior);
2024-12-26 02:18:47 +00:00
event AddedToken(
uint64 indexed chainId,
address indexed addr,
string name,
string symbol,
uint8 decimals,
uint32 transferGas,
uint16 indexed nonce
);
event UpdatedInstance(
uint64 indexed chainId,
address indexed addr,
uint256 denomination,
address indexed tokenAddress,
bool instanceApproval,
bool isOptional,
bool isDisabled,
uint16 nonce,
bool pushed
);
event UpdatedOwner(address indexed newOwner);
address public owner;
// Info revision so that infos pushed will be immutable per revision
uint16 public revision;
/**
* Chain Storage
*/
// list of chainIds
uint64[] public chainIds;
mapping(uint64 => bool) public hasChainId;
// revision => chainId => netInfo
mapping(uint16 => mapping(uint64 => bytes)) public netInfos;
/**
* RPC Storage
*/
mapping(bytes32 => RpcInfo) public rpcInfos;
EnumerableSet.Bytes32Set private rpchashes;
/**
* Token Storage
*/
TokenInfo[] public tokens;
// chainId => address
mapping(uint64 => mapping(address => uint16)) public tokenNonce;
/**
* Instance Storage
*/
InstanceInfo[] public instances;
// chainId => address
mapping(uint64 => mapping(address => uint16)) public instanceNonce;
modifier onlyOwner() {
require(msg.sender == owner, 'Not owner');
_;
}
constructor() {
owner = msg.sender;
emit UpdatedOwner(owner);
}
/**
* @dev Revision == dbSchema version
2025-01-05 09:29:24 +00:00
*
2024-12-26 02:18:47 +00:00
* Bump only when wrong info is pushed by mistake (should push all infos as well)
*/
function bumpRevision() external onlyOwner {
revision++;
2025-01-05 09:29:24 +00:00
emit BumpedRevision(revision);
2024-12-26 02:18:47 +00:00
}
function addChain(uint64 chainId, bytes memory netInfo) public onlyOwner {
if (!hasChainId[chainId]) {
chainIds.push(chainId);
hasChainId[chainId] = true;
}
require(netInfos[revision][chainId].length == 0, 'Already added');
netInfos[revision][chainId] = netInfo;
emit AddedChain(revision, chainId, netInfo);
}
function addRpc(uint64 chainId, string memory url, bool isPrior) public onlyOwner {
bytes32 rpchash = keccak256(abi.encodePacked(chainId, url, isPrior));
if (!rpchashes.contains(rpchash)) {
rpchashes.add(rpchash);
2025-01-05 09:29:24 +00:00
rpcInfos[rpchash] = RpcInfo({ chainId: chainId, url: url, isPrior: isPrior });
2024-12-26 02:18:47 +00:00
emit AddedRpc(chainId, url, isPrior);
} else {
rpchashes.remove(rpchash);
emit RemovedRpc(chainId, url, isPrior);
}
}
function addToken(TokenInfo memory token) public onlyOwner {
uint16 nonce = tokenNonce[token.chainId][token.addr];
require(tokens.length == 0 || nonce == 0, 'Duplicated token');
nonce = uint16(tokens.length);
tokens.push(token);
tokenNonce[token.chainId][token.addr] = nonce;
2025-01-05 09:29:24 +00:00
emit AddedToken(token.chainId, token.addr, token.name, token.symbol, token.decimals, token.transferGas, nonce);
2024-12-26 02:18:47 +00:00
}
function updateInstance(InstanceInfo memory instance) public onlyOwner {
uint16 nonce = instanceNonce[instance.chainId][instance.addr];
bool pushed;
// Push new instance
if (instances.length == 0 || nonce == 0) {
nonce = uint16(instances.length);
pushed = true;
instances.push(instance);
instanceNonce[instance.chainId][instance.addr] = nonce;
2025-01-05 09:29:24 +00:00
// Update limited data
2024-12-26 02:18:47 +00:00
} else {
instances[nonce].isOptional = instance.isOptional;
instances[nonce].isDisabled = instance.isDisabled;
}
emit UpdatedInstance(
instance.chainId,
instance.addr,
instance.denomination,
instance.tokenAddress,
instance.instanceApproval,
instance.isOptional,
instance.isDisabled,
nonce,
pushed
);
}
struct NetInfo {
uint64 chainId;
bytes netInfo;
}
function addInfos(
NetInfo[] memory _chains,
RpcInfo[] memory _rpcs,
TokenInfo[] memory _tokens,
InstanceInfo[] memory _instances
) external {
for (uint i; i < _chains.length; ++i) {
addChain(_chains[i].chainId, _chains[i].netInfo);
}
for (uint i; i < _rpcs.length; ++i) {
addRpc(_rpcs[i].chainId, _rpcs[i].url, _rpcs[i].isPrior);
}
for (uint i; i < _tokens.length; ++i) {
addToken(_tokens[i]);
}
for (uint i; i < _instances.length; ++i) {
updateInstance(_instances[i]);
}
}
function updateOwner(address newOwner) external onlyOwner {
owner = newOwner;
emit UpdatedOwner(newOwner);
}
function getChainIds() external view returns (uint64[] memory) {
uint64[] memory chains = new uint64[](chainIds.length);
for (uint i; i < chainIds.length; ++i) {
chains[i] = chainIds[i];
}
return chains;
}
/**
* @dev Revision should be constant value by UI
*/
function getNetInfos(uint16 _revision) external view returns (bytes[] memory) {
bytes[] memory infos = new bytes[](chainIds.length);
for (uint i; i < infos.length; ++i) {
infos[i] = netInfos[_revision][chainIds[i]];
}
return infos;
}
function getRpcs() external view returns (RpcInfo[] memory) {
RpcInfo[] memory rpcs = new RpcInfo[](rpchashes.length());
for (uint i; i < rpcs.length; ++i) {
rpcs[i] = rpcInfos[rpchashes.at(i)];
}
return rpcs;
}
function getRpchashes() external view returns (bytes32[] memory) {
return rpchashes.values();
}
function getInstances() external view returns (InstanceInfo[] memory) {
InstanceInfo[] memory _instances = new InstanceInfo[](instances.length);
for (uint i; i < instances.length; ++i) {
_instances[i] = instances[i];
}
return _instances;
}
function getTokens() external view returns (TokenInfo[] memory) {
TokenInfo[] memory _tokens = new TokenInfo[](tokens.length);
for (uint i; i < tokens.length; ++i) {
_tokens[i] = tokens[i];
}
return _tokens;
}
2025-01-05 09:29:24 +00:00
}