Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ cache/
broadcast/

contracts/flattened/*.sol
contracts/flattened/ens/*.sol

# foundry lib
lib/forge-std/
Expand Down
41 changes: 41 additions & 0 deletions abi/ENSRegistry.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

╭-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------╮
| Type | Signature | Selector |
+==========================================================================================================================================================+
| event | ApprovalForAll(address,address,bool) | 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| event | NewOwner(bytes32,bytes32,address) | 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| event | NewResolver(bytes32,address) | 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| event | NewTTL(bytes32,uint64) | 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| event | Transfer(bytes32,address) | 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | isApprovedForAll(address,address) view returns (bool) | 0xe985e9c5 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | owner(bytes32) view returns (address) | 0x02571be3 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | recordExists(bytes32) view returns (bool) | 0xf79fe538 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | resolver(bytes32) view returns (address) | 0x0178b8bf |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | setApprovalForAll(address,bool) nonpayable | 0xa22cb465 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | setOwner(bytes32,address) nonpayable | 0x5b0fc9c3 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | setRecord(bytes32,address,address,uint64) nonpayable | 0xcf408823 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | setResolver(bytes32,address) nonpayable | 0x1896f70a |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | setSubnodeOwner(bytes32,bytes32,address) nonpayable returns (bytes32) | 0x06ab5923 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | setSubnodeRecord(bytes32,bytes32,address,address,uint64) nonpayable | 0x5ef2c7f0 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | setTTL(bytes32,uint64) nonpayable | 0x14ab9038 |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| function | ttl(bytes32) view returns (uint64) | 0x16a25cbd |
|-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------|
| constructor | constructor() nonpayable | |
╰-------------+-----------------------------------------------------------------------+--------------------------------------------------------------------╯

65 changes: 65 additions & 0 deletions contracts/ens/ENS.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

interface ENS {
// Logged when the owner of a node assigns a new owner to a subnode.
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);

// Logged when the owner of a node transfers ownership to a new account.
event Transfer(bytes32 indexed node, address owner);

// Logged when the resolver for a node changes.
event NewResolver(bytes32 indexed node, address resolver);

// Logged when the TTL of a node changes
event NewTTL(bytes32 indexed node, uint64 ttl);

// Logged when an operator is added or removed.
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);

function setRecord(
bytes32 node,
address owner,
address resolver,
uint64 ttl
) external;

function setSubnodeRecord(
bytes32 node,
bytes32 label,
address owner,
address resolver,
uint64 ttl
) external;

function setSubnodeOwner(
bytes32 node,
bytes32 label,
address owner
) external returns (bytes32);

function setResolver(bytes32 node, address resolver) external;

function setOwner(bytes32 node, address owner) external;

function setTTL(bytes32 node, uint64 ttl) external;

function setApprovalForAll(address operator, bool approved) external;

function owner(bytes32 node) external view returns (address);

function resolver(bytes32 node) external view returns (address);

function ttl(bytes32 node) external view returns (uint64);

function recordExists(bytes32 node) external view returns (bool);

function isApprovedForAll(
address owner,
address operator
) external view returns (bool);
}
189 changes: 189 additions & 0 deletions contracts/ens/ENSRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
pragma solidity >=0.8.4;

import "./ENS.sol";

/// The ENS registry contract.
contract ENSRegistry is ENS {
struct Record {
address owner;
address resolver;
uint64 ttl;
}

mapping(bytes32 => Record) records;
mapping(address => mapping(address => bool)) operators;

// Permits modifications only by the owner of the specified node.
modifier authorised(bytes32 node) {
address owner = records[node].owner;
require(owner == msg.sender || operators[owner][msg.sender]);
_;
}

/// @dev Constructs a new ENS registry.
constructor() public {
records[0x0].owner = msg.sender;
}

/// @dev Sets the record for a node.
/// @param node The node to update.
/// @param owner The address of the new owner.
/// @param resolver The address of the resolver.
/// @param ttl The TTL in seconds.
function setRecord(
bytes32 node,
address owner,
address resolver,
uint64 ttl
) external virtual override {
setOwner(node, owner);
_setResolverAndTTL(node, resolver, ttl);
}

/// @dev Sets the record for a subnode.
/// @param node The parent node.
/// @param label The hash of the label specifying the subnode.
/// @param owner The address of the new owner.
/// @param resolver The address of the resolver.
/// @param ttl The TTL in seconds.
function setSubnodeRecord(
bytes32 node,
bytes32 label,
address owner,
address resolver,
uint64 ttl
) external virtual override {
bytes32 subnode = setSubnodeOwner(node, label, owner);
_setResolverAndTTL(subnode, resolver, ttl);
}

/// @dev Transfers ownership of a node to a new address. May only be called by the current owner of the node.
/// @param node The node to transfer ownership of.
/// @param owner The address of the new owner.
function setOwner(
bytes32 node,
address owner
) public virtual override authorised(node) {
_setOwner(node, owner);
emit Transfer(node, owner);
}

/// @dev Transfers ownership of a subnode keccak256(node, label) to a new address. May only be called by the owner of the parent node.
/// @param node The parent node.
/// @param label The hash of the label specifying the subnode.
/// @param owner The address of the new owner.
function setSubnodeOwner(
bytes32 node,
bytes32 label,
address owner
) public virtual override authorised(node) returns (bytes32) {
bytes32 subnode = keccak256(abi.encodePacked(node, label));
_setOwner(subnode, owner);
emit NewOwner(node, label, owner);
return subnode;
}

/// @dev Sets the resolver address for the specified node.
/// @param node The node to update.
/// @param resolver The address of the resolver.
function setResolver(
bytes32 node,
address resolver
) public virtual override authorised(node) {
emit NewResolver(node, resolver);
records[node].resolver = resolver;
}

/// @dev Sets the TTL for the specified node.
/// @param node The node to update.
/// @param ttl The TTL in seconds.
function setTTL(
bytes32 node,
uint64 ttl
) public virtual override authorised(node) {
emit NewTTL(node, ttl);
records[node].ttl = ttl;
}

/// @dev Enable or disable approval for a third party ("operator") to manage
/// all of `msg.sender`'s ENS records. Emits the ApprovalForAll event.
/// @param operator Address to add to the set of authorized operators.
/// @param approved True if the operator is approved, false to revoke approval.
function setApprovalForAll(
address operator,
bool approved
) external virtual override {
operators[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}

/// @dev Returns the address that owns the specified node.
/// @param node The specified node.
/// @return address of the owner.
function owner(
bytes32 node
) public view virtual override returns (address) {
address addr = records[node].owner;
if (addr == address(this)) {
return address(0x0);
}

return addr;
}

/// @dev Returns the address of the resolver for the specified node.
/// @param node The specified node.
/// @return address of the resolver.
function resolver(
bytes32 node
) public view virtual override returns (address) {
return records[node].resolver;
}

/// @dev Returns the TTL of a node, and any records associated with it.
/// @param node The specified node.
/// @return ttl of the node.
function ttl(bytes32 node) public view virtual override returns (uint64) {
return records[node].ttl;
}

/// @dev Returns whether a record has been imported to the registry.
/// @param node The specified node.
/// @return Bool if record exists
function recordExists(
bytes32 node
) public view virtual override returns (bool) {
return records[node].owner != address(0x0);
}

/// @dev Query if an address is an authorized operator for another address.
/// @param owner The address that owns the records.
/// @param operator The address that acts on behalf of the owner.
/// @return True if `operator` is an approved operator for `owner`, false otherwise.
function isApprovedForAll(
address owner,
address operator
) external view virtual override returns (bool) {
return operators[owner][operator];
}

function _setOwner(bytes32 node, address owner) internal virtual {
records[node].owner = owner;
}

function _setResolverAndTTL(
bytes32 node,
address resolver,
uint64 ttl
) internal {
if (resolver != records[node].resolver) {
records[node].resolver = resolver;
emit NewResolver(node, resolver);
}

if (ttl != records[node].ttl) {
records[node].ttl = ttl;
emit NewTTL(node, ttl);
}
}
}
7 changes: 7 additions & 0 deletions genesis-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@
"0x0000000000000000000000000000000000002006": {
"balance": "0x0",
"code": "{{timelock}}"
},
"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e": {
"balance": "0x0",
"code": "{{ensRegistry}}",
"storage": {
"0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5": "0x000000000000000000000000{{ensRegistryOwner}}"
}
}{% for v in initHolders %},
"{{ v.address.replace('0x', '') }}": {
"balance": "0x{{ v.balance }}"
Expand Down
7 changes: 7 additions & 0 deletions genesis.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"author": "",
"license": "MIT",
"scripts": {
"lint:check": "forge fmt ./contracts/L2PTimelock.sol ./contracts/GovToken.sol ./contracts/L2PGovernor.sol ./contracts/StakeCredit.sol ./contracts/StakeHub.sol ./contracts/SystemV2.sol --check",
"lint:write": "forge fmt ./contracts/L2PTimelock.sol ./contracts/GovToken.sol ./contracts/L2PGovernor.sol ./contracts/StakeCredit.sol ./contracts/StakeHub.sol ./contracts/SystemV2.sol ",
"lint:check": "forge fmt ./contracts/L2PTimelock.sol ./contracts/GovToken.sol ./contracts/L2PGovernor.sol ./contracts/StakeCredit.sol ./contracts/StakeHub.sol ./contracts/SystemV2.sol ./contracts/ens/ENSRegistry.sol ./contracts/ens/ENS.sol --check",
"lint:write": "forge fmt ./contracts/L2PTimelock.sol ./contracts/GovToken.sol ./contracts/L2PGovernor.sol ./contracts/StakeCredit.sol ./contracts/StakeHub.sol ./contracts/SystemV2.sol ./contracts/ens/ENSRegistry.sol ./contracts/ens/ENS.sol ",
"generate:mainnet": "poetry run python -m scripts.generate mainnet",
"generate:testnet": "poetry run python -m scripts.generate testnet",
"generate:dev": "poetry run python -m scripts.generate dev --init-burn-ratio \"1000\" --init-felony-slash-scope \"60\" --breathe-block-interval \"10 minutes\" --block-interval \"3 seconds\" --stake-hub-protector \"0x04d63aBCd2b9b1baa327f2Dda0f873F197ccd186\" --unbond-period \"2 minutes\" --downtime-jail-time \"2 minutes\" --felony-jail-time \"3 minutes\" --init-voting-period \"2 minutes / BLOCK_INTERVAL\" --init-min-period-after-quorum \"uint64(1 minutes / BLOCK_INTERVAL)\" --governor-protector \"0x04d63aBCd2b9b1baa327f2Dda0f873F197ccd186\" --init-minimal-delay \"1 minutes\" --token-recover-portal-protector \"0x04d63aBCd2b9b1baa327f2Dda0f873F197ccd186\""
Expand Down
1 change: 1 addition & 0 deletions scripts/flatten.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ forge flatten contracts/StakeCredit.sol -o contracts/flattened/StakeCredit.sol
forge flatten contracts/L2PGovernor.sol -o contracts/flattened/L2PGovernor.sol
forge flatten contracts/GovToken.sol -o contracts/flattened/GovToken.sol
forge flatten contracts/L2PTimelock.sol -o contracts/flattened/L2PTimelock.sol
forge flatten contracts/ens/ENSRegistry.sol -o contracts/flattened/ens/ENSRegistry.sol
5 changes: 4 additions & 1 deletion scripts/generate-genesis.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const init_holders = require('./init_holders');

program.version('0.0.1');
program.option('-c, --chainId <chainId>', 'chain id', '714');
program.option('-e, --ensRegistryOwner <ens-registry-owner-address>', 'ens registry owner address', '0x...');
program.option('-o, --output <output-file>', 'Genesis json file', './genesis.json');
program.option('-t, --template <template>', 'Genesis template json', './genesis-template.json');
program.parse(process.argv);
Expand Down Expand Up @@ -46,12 +47,14 @@ Promise.all([
readByteCode('stakeCredit', 'out/StakeCredit.sol/StakeCredit.json'),
readByteCode('governor', 'out/L2PGovernor.sol/L2PGovernor.json'),
readByteCode('govToken', 'out/GovToken.sol/GovToken.json'),
readByteCode('timelock', 'out/L2PTimelock.sol/L2PTimelock.json')
readByteCode('timelock', 'out/L2PTimelock.sol/L2PTimelock.json'),
readByteCode('ensRegistry', 'out/ENSRegistry.sol/ENSRegistry.json')
]).then((result) => {
const data = {
chainId: program.chainId,
initHolders: init_holders,
extraData: web3.utils.bytesToHex(validators.extraValidatorBytes),
ensRegistryOwner: program.ensRegistryOwner.slice(2).toLowerCase(),
};

result.forEach((r) => {
Expand Down
6 changes: 4 additions & 2 deletions scripts/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
network: str
chain_id: int
hex_chain_id: str
ens_registry_owner: str

main = typer.Typer()

Expand Down Expand Up @@ -210,14 +211,15 @@ def generate_gov_hub():

def generate_genesis(output="./genesis.json"):
subprocess.run(["forge", "build"], cwd=work_dir, check=True)
subprocess.run(["node", "scripts/generate-genesis.js", "--chainId", f"{chain_id}", "--output", f"{output}"], cwd=work_dir, check=True)
subprocess.run(["node", "scripts/generate-genesis.js", "--chainId", f"{chain_id}", "--ensRegistryOwner", f"{ens_registry_owner}", "--output", f"{output}"], cwd=work_dir, check=True)


@main.command(help="Generate contracts for L2P mainnet")
def mainnet():
global network, chain_id, hex_chain_id
global network, chain_id, hex_chain_id, ens_registry_owner
network = "mainnet"
chain_id = 12216
ens_registry_owner = "0x1B272dC2635CFBE67116434CdBfD7525f8F5196F"
hex_chain_id = convert_chain_id(chain_id)

# mainnet init data
Expand Down
Loading